diff --git a/inputcontext/QskInputContext.cpp b/inputcontext/QskInputContext.cpp index 52e80b6b..6a944310 100644 --- a/inputcontext/QskInputContext.cpp +++ b/inputcontext/QskInputContext.cpp @@ -8,6 +8,7 @@ #include "QskInputCompositionModel.h" #include "QskPinyinCompositionModel.h" +#include "QskHunspellCompositionModel.h" #include #include @@ -78,7 +79,11 @@ QskInputContext::QskInputContext(): { setObjectName( "InputContext" ); +#if 1 m_data->compositionModel = new QskInputCompositionModel( this ); +#else + m_data->compositionModel = new QskHunspellCompositionModel( this ); +#endif connect( m_data->compositionModel, &QskInputCompositionModel::candidatesChanged, this, &QskInputContext::handleCandidatesChanged ); diff --git a/playground/inputpanel/main.cpp b/playground/inputpanel/main.cpp index 24fc6e32..8379a3eb 100644 --- a/playground/inputpanel/main.cpp +++ b/playground/inputpanel/main.cpp @@ -42,6 +42,7 @@ public: auto* textInput = new QskTextInput( this ); textInput->setText( "I am a line edit. Press and edit Me." ); textInput->setSelectByMouse( true ); + textInput->setSizePolicy( Qt::Horizontal, QskSizePolicy::Preferred ); #if LOCAL_PANEL auto* inputPanel = new QskVirtualKeyboard( this ); diff --git a/src/controls/QskTextInput.cpp b/src/controls/QskTextInput.cpp index f409c20c..b276a127 100644 --- a/src/controls/QskTextInput.cpp +++ b/src/controls/QskTextInput.cpp @@ -4,11 +4,19 @@ *****************************************************************************/ #include "QskTextInput.h" -#include "QskTextOptions.h" + +// VS2012+ disable keyword macroizing unless _ALLOW_KEYWORD_MACROS is set +#ifdef _MSC_VER +#if ( _MSC_VER >= 1700 ) && !defined( _ALLOW_KEYWORD_MACROS ) +#define _ALLOW_KEYWORD_MACROS +#endif +#endif QSK_QT_PRIVATE_BEGIN +#define private public #include #include +#undef private QSK_QT_PRIVATE_END static inline void qskBindSignals( const QQuickTextInput* wrappedInput, @@ -69,12 +77,19 @@ namespace class TextInput final : public QQuickTextInput { public: - TextInput( QQuickItem* parent ) : + TextInput( QQuickItem* parent ): QQuickTextInput( parent ) { + classBegin(); + setActiveFocusOnTab( false ); setFlag( ItemAcceptsInputMethod, false ); setFocusOnPress( false ); + + connect( this, &TextInput::contentSizeChanged, + this, &TextInput::updateClip ); + + componentComplete(); } void setAlignment( Qt::Alignment alignment ) @@ -85,23 +100,90 @@ namespace inline bool handleEvent( QEvent* event ) { - switch( event->type() ) + return QQuickTextInput::event( event ); + } + + virtual void focusInEvent( QFocusEvent* ) override + { + auto d = QQuickTextInputPrivate::get( this ); + + if ( d->m_readOnly ) + return; + + d->cursorVisible = true; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + d->updateCursorBlinking(); + d->setBlinkingCursorEnabled( true ); +#endif + + if ( d->determineHorizontalAlignment() ) { - case QEvent::FocusIn: - case QEvent::FocusOut: - { - auto d = QQuickTextInputPrivate::get( this ); + d->updateLayout(); + d->updateHorizontalScroll(); + d->updateVerticalScroll(); - d->focusOnPress = true; - d->handleFocusEvent( static_cast< QFocusEvent* >( event ) ); - d->focusOnPress = false; - - return true; - } - - default: - return QQuickTextInput::event( event ); +#if 0 + updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); +#endif } + + connect( QGuiApplication::inputMethod(), + SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), + this, SLOT(q_updateAlignment()) ); + + qGuiApp->inputMethod()->show(); + } + + virtual void focusOutEvent( QFocusEvent* event ) override + { + auto d = QQuickTextInputPrivate::get( this ); + + if (d->m_readOnly) + return; + + d->cursorVisible = false; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + d->updateCursorBlinking(); + d->setBlinkingCursorEnabled( false ); +#endif + + if ( d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive() ) + { + d->updatePasswordEchoEditing( false ); + } + + if ( event->reason() != Qt::ActiveWindowFocusReason + && event->reason() != Qt::PopupFocusReason ) + { + if ( d->hasSelectedText() && !d->persistentSelection ) + deselect(); + } + + const auto status = d->hasAcceptableInput( d->m_text ); + if ( status == QQuickTextInputPrivate::AcceptableInput ) + { + if ( d->fixup() ) + Q_EMIT editingFinished(); + } + + disconnect( QGuiApplication::inputMethod(), + SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), + this, SLOT(q_updateAlignment()) ); + } + + virtual void geometryChanged( + const QRectF& newGeometry, const QRectF& oldGeometry ) override + { + QQuickTextInput::geometryChanged( newGeometry, oldGeometry ); + updateClip(); + } + + void updateClip() + { + setClip( ( contentWidth() > width() ) || + ( contentHeight() > height() ) ); } }; } @@ -276,16 +358,6 @@ void QskTextInput::setFontRole( int role ) } } -QskTextOptions QskTextInput::textOptions() const -{ - return QskTextOptions(); -} - -void QskTextInput::setTextOptions( const QskTextOptions& options ) -{ - Q_UNUSED( options ) -} - void QskTextInput::setAlignment( Qt::Alignment alignment ) { if ( alignment != this->alignment() ) @@ -325,6 +397,11 @@ void QskTextInput::setReadOnly( bool on ) qskUpdateInputMethod( this, Qt::ImEnabled ); } +void QskTextInput::ensureVisible( int position ) +{ + m_data->textInput->ensureVisible( position ); +} + bool QskTextInput::isCursorVisible() const { return m_data->textInput->isCursorVisible(); @@ -507,7 +584,9 @@ QVariant QskTextInput::inputMethodQuery( return locale(); } case Qt::ImCursorRectangle: +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) case Qt::ImInputItemClipRectangle: +#endif { QVariant v = m_data->textInput->inputMethodQuery( query, argument ); #if 1 diff --git a/src/controls/QskTextInput.h b/src/controls/QskTextInput.h index e77d7738..28080b3d 100644 --- a/src/controls/QskTextInput.h +++ b/src/controls/QskTextInput.h @@ -8,7 +8,6 @@ #include "QskControl.h" -class QskTextOptions; class QValidator; class QSK_EXPORT QskTextInput : public QskControl @@ -20,9 +19,6 @@ class QSK_EXPORT QskTextInput : public QskControl Q_PROPERTY( int fontRole READ fontRole WRITE setFontRole NOTIFY fontRoleChanged ) - Q_PROPERTY( QskTextOptions textOptions READ textOptions - WRITE setTextOptions NOTIFY textOptionsChanged ) - Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged ) @@ -57,9 +53,6 @@ public: void setFontRole( int role ); int fontRole() const; - void setTextOptions( const QskTextOptions& ); - QskTextOptions textOptions() const; - void setAlignment( Qt::Alignment ); Qt::Alignment alignment() const; @@ -124,6 +117,8 @@ public: Qt::InputMethodHints inputMethodHints() const; void setInputMethodHints( Qt::InputMethodHints ); + void ensureVisible( int position ); + public Q_SLOTS: void setText( const QString& ); diff --git a/src/inputpanel/QskVirtualKeyboard.cpp b/src/inputpanel/QskVirtualKeyboard.cpp index d7bae088..0ce7a66c 100644 --- a/src/inputpanel/QskVirtualKeyboard.cpp +++ b/src/inputpanel/QskVirtualKeyboard.cpp @@ -198,10 +198,22 @@ static bool qskIsAutorepeat( int key ) && key != Qt::Key_Mode_switch ); } -static inline QPlatformInputContext* qskInputContext() +static inline QQuickItem* qskInputItem() { - auto inputMethod = QGuiApplication::inputMethod(); - return QInputMethodPrivate::get( inputMethod )->platformInputContext(); + QPlatformInputContext* inputContext; +#if 1 + inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); +#else + // for some reason the gcc sanitizer does not like this one + inputContext = QInputMethodPrivate::get( inputMethod )->platformInputContext(); +#endif + + QQuickItem* item = nullptr; + + QMetaObject::invokeMethod( inputContext, "inputItem", + Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, item ) ); + + return item; } QSK_SUBCONTROL( QskVirtualKeyboard, Panel ) @@ -536,19 +548,12 @@ bool QskVirtualKeyboard::eventFilter( QObject* object, QEvent* event ) always has the focus. But this does not work, when a virtual keyboard is used, where you can navigate and select inside. So we have to fix the receiver. + + Maybe QEvent::EnterEditFocus is good for something ?? */ - if ( const auto inputContext = qskInputContext() ) - { - QQuickItem* item = nullptr; - - if ( QMetaObject::invokeMethod( inputContext, "inputItem", - Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, item ) ) ) - { - if ( item ) - QGuiApplication::sendEvent( item, event ); - } - } + if ( auto item = qskInputItem() ) + QGuiApplication::sendEvent( item, event ); return true; } @@ -556,4 +561,13 @@ bool QskVirtualKeyboard::eventFilter( QObject* object, QEvent* event ) return Inherited::eventFilter( object, event ); } +bool QskVirtualKeyboard::event( QEvent* event ) +{ + /* + Handling Qt::Key_Return/Qt::KeyEscape here + and forward everything else to the input item TODO ... + */ + return Inherited::event( event ); +} + #include "moc_QskVirtualKeyboard.cpp" diff --git a/src/inputpanel/QskVirtualKeyboard.h b/src/inputpanel/QskVirtualKeyboard.h index 6d2efbc5..dcc5392d 100644 --- a/src/inputpanel/QskVirtualKeyboard.h +++ b/src/inputpanel/QskVirtualKeyboard.h @@ -54,6 +54,8 @@ public Q_SLOTS: protected: virtual bool eventFilter( QObject*, QEvent* ) override; + virtual bool event( QEvent* ) override; + virtual void updateLayout() override; private Q_SLOTS: