2018-04-06 15:30:24 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
#include "QskInputPanel.h"
|
2018-06-11 16:55:48 +00:00
|
|
|
#include "QskInputContext.h"
|
|
|
|
#include "QskTextPredictor.h"
|
|
|
|
|
2018-04-26 12:42:33 +00:00
|
|
|
#include <QPointer>
|
2018-06-11 16:55:48 +00:00
|
|
|
#include <QTextCharFormat>
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
static inline QQuickItem* qskReceiverItem( const QskInputPanel* panel )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
if ( auto item = panel->inputProxy() )
|
|
|
|
return item;
|
|
|
|
|
|
|
|
return panel->inputItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool qskUsePrediction( Qt::InputMethodHints hints )
|
|
|
|
{
|
|
|
|
constexpr Qt::InputMethodHints mask =
|
|
|
|
Qt::ImhNoPredictiveText | Qt::ImhExclusiveInputMask | Qt::ImhHiddenText;
|
|
|
|
|
|
|
|
return ( hints & mask ) == 0;
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2018-04-18 17:41:46 +00:00
|
|
|
namespace
|
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
class KeyProcessor
|
2018-04-18 17:41:46 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-06-12 06:20:48 +00:00
|
|
|
struct Result
|
2018-04-18 17:41:46 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
int key = 0;
|
2018-06-05 14:55:36 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
QString text;
|
|
|
|
bool isFinal = true;
|
|
|
|
};
|
2018-06-01 15:26:22 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
Result processKey(
|
|
|
|
int key, Qt::InputMethodHints inputHints,
|
2018-06-11 16:55:48 +00:00
|
|
|
QskTextPredictor* predictor, int spaceLeft )
|
2018-04-27 14:55:50 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
Result result;
|
|
|
|
|
|
|
|
// First we have to handle the control keys
|
|
|
|
|
|
|
|
switch ( key )
|
|
|
|
{
|
|
|
|
case Qt::Key_Backspace:
|
|
|
|
case Qt::Key_Muhenkan:
|
|
|
|
{
|
|
|
|
if ( predictor )
|
|
|
|
{
|
|
|
|
if ( !m_preedit.isEmpty() )
|
|
|
|
{
|
|
|
|
m_preedit.chop( 1 );
|
|
|
|
|
|
|
|
result.text = m_preedit;
|
|
|
|
result.isFinal = false;
|
|
|
|
|
|
|
|
predictor->request( m_preedit );
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result.key = Qt::Key_Backspace;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
case Qt::Key_Return:
|
|
|
|
{
|
|
|
|
if ( predictor )
|
|
|
|
{
|
|
|
|
if ( !m_preedit.isEmpty() )
|
|
|
|
{
|
|
|
|
if ( spaceLeft )
|
|
|
|
{
|
|
|
|
result.text = m_preedit.left( spaceLeft );
|
|
|
|
result.isFinal = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
reset();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !( inputHints & Qt::ImhMultiLine ) )
|
|
|
|
{
|
|
|
|
result.key = Qt::Key_Return;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Qt::Key_Space:
|
|
|
|
{
|
|
|
|
if ( predictor )
|
|
|
|
{
|
|
|
|
if ( !m_preedit.isEmpty() && spaceLeft)
|
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
m_preedit += keyString( key );
|
2018-06-11 16:55:48 +00:00
|
|
|
m_preedit = m_preedit.left( spaceLeft );
|
|
|
|
|
|
|
|
result.text = m_preedit;
|
|
|
|
result.isFinal = true;
|
|
|
|
|
|
|
|
reset();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Qt::Key_Left:
|
|
|
|
case Qt::Key_Right:
|
|
|
|
case Qt::Key_Escape:
|
|
|
|
{
|
|
|
|
result.key = key;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
const QString text = keyString( key );
|
2018-06-11 16:55:48 +00:00
|
|
|
|
|
|
|
if ( predictor )
|
|
|
|
{
|
|
|
|
m_preedit += text;
|
|
|
|
|
|
|
|
predictor->request( m_preedit );
|
|
|
|
|
|
|
|
if ( predictor->candidateCount() > 0 )
|
|
|
|
{
|
|
|
|
result.text = m_preedit;
|
|
|
|
result.isFinal = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.text = m_preedit.left( spaceLeft );
|
|
|
|
result.isFinal = true;
|
|
|
|
|
|
|
|
m_preedit.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.text = text;
|
|
|
|
result.isFinal = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2018-04-27 14:55:50 +00:00
|
|
|
}
|
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
void reset()
|
2018-04-27 14:55:50 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
m_preedit.clear();
|
2018-04-18 17:41:46 +00:00
|
|
|
}
|
2018-06-05 14:55:36 +00:00
|
|
|
|
|
|
|
private:
|
2018-06-12 06:20:48 +00:00
|
|
|
inline QString keyString( int keyCode ) const
|
|
|
|
{
|
|
|
|
// Special case entry codes here, else default to the symbol
|
|
|
|
switch ( keyCode )
|
|
|
|
{
|
|
|
|
case Qt::Key_Shift:
|
|
|
|
case Qt::Key_CapsLock:
|
|
|
|
case Qt::Key_Mode_switch:
|
|
|
|
case Qt::Key_Backspace:
|
|
|
|
case Qt::Key_Muhenkan:
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Kanji:
|
|
|
|
return QChar( QChar::CarriageReturn );
|
|
|
|
|
|
|
|
case Qt::Key_Space:
|
|
|
|
return QChar( QChar::Space );
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QChar( keyCode );
|
|
|
|
}
|
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
QString m_preedit;
|
2018-04-18 17:41:46 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
class QskInputPanel::PrivateData
|
2018-04-10 14:51:35 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-06-11 16:55:48 +00:00
|
|
|
KeyProcessor keyProcessor;
|
2018-04-26 12:42:33 +00:00
|
|
|
QPointer< QQuickItem > inputItem;
|
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
QLocale predictorLocale;
|
|
|
|
QPointer< QskTextPredictor > predictor;
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
Qt::InputMethodHints inputHints = 0;
|
|
|
|
bool hasPredictorLocale = false;
|
2018-04-10 14:51:35 +00:00
|
|
|
};
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
QskInputPanel::QskInputPanel( QQuickItem* parent ):
|
2018-04-18 17:41:46 +00:00
|
|
|
Inherited( parent ),
|
2018-04-10 14:51:35 +00:00
|
|
|
m_data( new PrivateData() )
|
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
setAutoLayoutChildren( true );
|
|
|
|
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Constrained );
|
|
|
|
|
|
|
|
connect( this, &QskInputPanel::keySelected,
|
|
|
|
this, &QskInputPanel::commitKey );
|
|
|
|
|
|
|
|
connect( this, &QskInputPanel::predictiveTextSelected,
|
|
|
|
this, &QskInputPanel::commitPredictiveText );
|
|
|
|
|
|
|
|
connect( this, &QskControl::localeChanged,
|
|
|
|
this, &QskInputPanel::updateLocale );
|
|
|
|
|
|
|
|
updateLocale( locale() );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-04-10 14:51:35 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
QskInputPanel::~QskInputPanel()
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
|
|
|
}
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::attachInputItem( QQuickItem* item )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
|
|
|
if ( item == m_data->inputItem )
|
|
|
|
return;
|
2018-04-10 14:51:35 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
m_data->inputItem = item;
|
2018-04-10 14:51:35 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( item )
|
|
|
|
{
|
|
|
|
auto context = QskInputContext::instance();
|
|
|
|
const auto locale = context->locale();
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( m_data->predictor )
|
|
|
|
m_data->predictor->reset();
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
m_data->keyProcessor.reset();
|
|
|
|
m_data->inputHints = 0;
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
attachItem( item );
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
Qt::InputMethodQueries queries = Qt::ImQueryAll;
|
|
|
|
queries &= ~Qt::ImEnabled;
|
2018-04-10 14:51:35 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
updateInputPanel( queries );
|
2018-06-12 06:20:48 +00:00
|
|
|
|
|
|
|
if ( inputProxy() )
|
|
|
|
{
|
|
|
|
// hiding the cursor in item
|
|
|
|
const QInputMethodEvent::Attribute attribute(
|
|
|
|
QInputMethodEvent::Cursor, 0, 0, QVariant() );
|
|
|
|
|
|
|
|
QInputMethodEvent event( QString(), { attribute } );
|
|
|
|
QCoreApplication::sendEvent( item, &event );
|
|
|
|
}
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
attachItem( nullptr );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-04-10 14:51:35 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::updateInputPanel( Qt::InputMethodQueries queries )
|
2018-04-10 14:51:35 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
if ( m_data->inputItem == nullptr )
|
2018-06-11 16:55:48 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
QInputMethodQueryEvent event( queries );
|
2018-06-12 06:20:48 +00:00
|
|
|
QCoreApplication::sendEvent( m_data->inputItem, &event );
|
2018-06-11 16:55:48 +00:00
|
|
|
|
|
|
|
if ( queries & Qt::ImHints )
|
|
|
|
{
|
|
|
|
m_data->inputHints = static_cast< Qt::InputMethodHints >(
|
|
|
|
event.value( Qt::ImHints ).toInt() );
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
setPredictionEnabled(
|
|
|
|
m_data->predictor && qskUsePrediction( m_data->inputHints ) );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( queries & Qt::ImPreferredLanguage )
|
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
setLocale( event.value( Qt::ImPreferredLanguage ).toLocale() );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-04-10 14:51:35 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::updateLocale( const QLocale& locale )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
|
|
|
if ( !m_data->hasPredictorLocale || locale != m_data->predictorLocale )
|
|
|
|
{
|
|
|
|
m_data->hasPredictorLocale = true;
|
|
|
|
m_data->predictorLocale = locale;
|
2018-04-12 10:03:51 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
resetPredictor( locale );
|
2018-06-11 16:55:48 +00:00
|
|
|
m_data->keyProcessor.reset();
|
|
|
|
}
|
2018-04-12 10:03:51 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::resetPredictor( const QLocale& locale )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
|
|
|
auto predictor = QskInputContext::instance()->textPredictor( locale );
|
2018-04-12 10:03:51 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( predictor == m_data->predictor )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( m_data->predictor )
|
2018-04-12 10:03:51 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( m_data->predictor->parent() == this )
|
2018-04-27 14:55:50 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
delete m_data->predictor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_data->predictor->disconnect( this );
|
|
|
|
m_data->predictor = nullptr;
|
|
|
|
}
|
|
|
|
}
|
2018-04-27 14:55:50 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
m_data->predictor = predictor;
|
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( predictor )
|
|
|
|
{
|
|
|
|
if ( predictor->parent() == nullptr )
|
|
|
|
predictor->setParent( this );
|
2018-04-27 14:55:50 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
connect( predictor, &QskTextPredictor::predictionChanged,
|
2018-06-12 06:20:48 +00:00
|
|
|
this, &QskInputPanel::updatePrediction );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
setPredictionEnabled(
|
|
|
|
predictor && qskUsePrediction( m_data->inputHints ) );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::commitPredictiveText( int index )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
QString text;
|
2018-06-11 16:55:48 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
if ( m_data->predictor )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
text = m_data->predictor->candidate( index );
|
|
|
|
m_data->predictor->reset();
|
2018-04-12 10:03:51 +00:00
|
|
|
}
|
2018-06-11 16:55:48 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
m_data->keyProcessor.reset();
|
|
|
|
|
|
|
|
setPrediction( QStringList() );
|
|
|
|
|
|
|
|
qskSendText( qskReceiverItem( this ), text, true );
|
2018-04-26 12:42:33 +00:00
|
|
|
}
|
2018-04-12 10:03:51 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::updatePrediction()
|
2018-04-26 12:42:33 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
if ( m_data->predictor )
|
|
|
|
setPrediction( m_data->predictor->candidates() );
|
2018-04-26 12:42:33 +00:00
|
|
|
}
|
2018-04-18 17:41:46 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
QQuickItem* QskInputPanel::inputProxy() const
|
2018-06-01 15:26:22 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
return nullptr;
|
2018-06-01 15:26:22 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
QQuickItem* QskInputPanel::inputItem() const
|
2018-04-26 12:42:33 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
return m_data->inputItem;
|
|
|
|
}
|
2018-06-05 14:55:36 +00:00
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::setPrompt( const QString& )
|
|
|
|
{
|
2018-04-12 10:03:51 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::setPredictionEnabled( bool )
|
2018-04-18 17:41:46 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::setPrediction( const QStringList& )
|
2018-04-18 17:41:46 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
Qt::Alignment QskInputPanel::alignment() const
|
2018-04-10 14:51:35 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
/*
|
|
|
|
When we have an input proxy, we don't care if
|
|
|
|
the input item becomes hidden
|
|
|
|
*/
|
|
|
|
|
|
|
|
return inputProxy() ? Qt::AlignVCenter : Qt::AlignBottom;
|
2018-04-10 14:51:35 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
void QskInputPanel::commitKey( int key )
|
2018-04-13 14:32:48 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
int spaceLeft = -1;
|
2018-04-13 14:32:48 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
if ( !( m_data->inputHints & Qt::ImhMultiLine ) )
|
2018-04-13 14:32:48 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
QInputMethodQueryEvent event1( Qt::ImMaximumTextLength );
|
2018-06-12 06:20:48 +00:00
|
|
|
QCoreApplication::sendEvent( m_data->inputItem, &event1 );
|
2018-04-13 14:32:48 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
const int maxChars = event1.value( Qt::ImMaximumTextLength ).toInt();
|
|
|
|
if ( maxChars >= 0 )
|
2018-04-13 14:32:48 +00:00
|
|
|
{
|
2018-06-11 16:55:48 +00:00
|
|
|
QInputMethodQueryEvent event2( Qt::ImSurroundingText );
|
|
|
|
QCoreApplication::sendEvent( qskReceiverItem( this ), &event2 );
|
2018-06-02 15:10:41 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
const auto text = event2.value( Qt::ImSurroundingText ).toString();
|
|
|
|
spaceLeft = maxChars - text.length();
|
2018-04-13 14:32:48 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-03 09:01:22 +00:00
|
|
|
|
2018-06-11 16:55:48 +00:00
|
|
|
QskTextPredictor* predictor = nullptr;
|
|
|
|
if ( qskUsePrediction( m_data->inputHints ) )
|
|
|
|
predictor = m_data->predictor;
|
|
|
|
|
|
|
|
const auto result = m_data->keyProcessor.processKey(
|
|
|
|
key, m_data->inputHints, predictor, spaceLeft );
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
switch( result.key )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
case 0:
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
if ( !result.text.isEmpty() )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
qskSendText( qskReceiverItem( this ),
|
|
|
|
result.text, result.isFinal );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-06-12 06:20:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Qt::Key_Return:
|
|
|
|
{
|
|
|
|
if ( auto proxy = inputProxy() )
|
2018-06-11 16:55:48 +00:00
|
|
|
{
|
2018-06-12 06:20:48 +00:00
|
|
|
// using input method query instead
|
|
|
|
const auto value = proxy->property( "text" );
|
|
|
|
if ( value.canConvert< QString >() )
|
|
|
|
{
|
|
|
|
qskSendReplaceText( m_data->inputItem, value.toString() );
|
|
|
|
}
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-06-12 06:20:48 +00:00
|
|
|
|
|
|
|
qskSendKey( m_data->inputItem, result.key );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Qt::Key_Escape:
|
|
|
|
{
|
|
|
|
qskSendKey( m_data->inputItem, result.key );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
qskSendKey( qskReceiverItem( this ), result.key );
|
2018-06-11 16:55:48 +00:00
|
|
|
}
|
2018-06-03 09:01:22 +00:00
|
|
|
}
|
2018-04-13 14:32:48 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 06:20:48 +00:00
|
|
|
#include "moc_QskInputPanel.cpp"
|