QskAbstractTextInput introduced - trying to bring the implementation of

QskTextEdit/QskTextInput together. work in progress
This commit is contained in:
Uwe Rathmann 2025-01-15 18:46:30 +01:00
parent 4fa3c6e5b7
commit 4fb9819767
14 changed files with 1062 additions and 1371 deletions

View File

@ -299,11 +299,8 @@ namespace
void setupTabViewMetrics();
void setupTabViewColors( QskAspect::Section, const QskFluent2Theme& );
template< typename Q >
void setupTextControlMetrics();
template< typename Q, typename SK >
void setupTextControlColors( QskAspect::Section section, const QskFluent2Theme& theme );
void setupTextInputMetrics();
void setupTextInputColors( QskAspect::Section, const QskFluent2Theme& );
void setupTextAreaMetrics();
void setupTextAreaColors( QskAspect::Section, const QskFluent2Theme& );
@ -367,6 +364,7 @@ void Editor::setupMetrics()
setupTabButtonMetrics();
setupTabBarMetrics();
setupTabViewMetrics();
setupTextInputMetrics();
setupTextAreaMetrics();
setupTextFieldMetrics();
setupTextLabelMetrics();
@ -407,6 +405,7 @@ void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& the
setupTabButtonColors( section, theme );
setupTabBarColors( section, theme );
setupTabViewColors( section, theme );
setupTextInputColors( section, theme );
setupTextAreaColors( section, theme );
setupTextFieldColors( section, theme );
setupTextLabelColors( section, theme );
@ -1794,8 +1793,34 @@ void Editor::setupTextLabelColors(
setColor( Q::Text | section, pal.fillColor.text.primary );
}
template< typename Q > void Editor::setupTextControlMetrics()
void Editor::setupTextInputMetrics()
{
using Q = QskAbstractTextInput;
setFontRole( Q::Text, Fluent2::Body );
}
void Editor::setupTextInputColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
using Q = QskAbstractTextInput;
const auto& pal = theme.palette;
const auto text = Q::Text | section;
#if 1
setColor( text, pal.fillColor.text.primary );
setColor( text | Q::Selected, pal.fillColor.textOnAccent.selectedText );
setColor( text | Q::Disabled, pal.fillColor.text.disabled );
#endif
}
void Editor::setupTextAreaMetrics()
{
using Q = QskTextArea;
// ===
setStrutSize( Q::TextPanel, { -1, 30_px } );
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
@ -1805,97 +1830,123 @@ template< typename Q > void Editor::setupTextControlMetrics()
setBoxShape( Q::TextPanel, 3_px );
setFontRole( Q::Text, Fluent2::Body );
setAlignment( Q::Placeholder, alignment( Q::Text ) );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
setFontRole( Q::Placeholder, fontRole( Q::Text ) );
}
template< typename Q, typename SK > void Editor::setupTextControlColors(
QskAspect::Section section, const QskFluent2Theme& theme)
void Editor::setupTextAreaColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
using A = QskAspect;
using Q = QskTextArea;
const auto& pal = theme.palette;
setColor( Q::TextPanel | SK::Selected, pal.fillColor.accent.selectedTextBackground );
setColor( Q::Text | SK::Selected, pal.fillColor.textOnAccent.selectedText );
setColor( Q::TextPanel | Q::Selected, pal.fillColor.accent.selectedTextBackground );
setColor( Q::Placeholder, pal.fillColor.text.secondary );
for( const auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Editing, Q::Disabled } )
{
QRgb panelColor, borderColor1, borderColor2, textColor;
QRgb panelColor, borderColor1, borderColor2;
if ( state == A::NoState )
{
panelColor = pal.fillColor.control.defaultColor;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.elevation.textControl.border[1];
textColor = pal.fillColor.text.primary;
}
else if ( state == Q::Hovered )
{
panelColor = pal.fillColor.control.secondary;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.elevation.textControl.border[1];
textColor = pal.fillColor.text.primary;
}
else if ( ( state == Q::Focused ) || ( state == Q::Editing ) )
{
panelColor = pal.fillColor.control.inputActive;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.fillColor.accent.defaultColor;
textColor = pal.fillColor.text.primary;
}
else if ( state == Q::Disabled )
{
panelColor = pal.fillColor.control.disabled;
borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor;
textColor = pal.fillColor.text.disabled;
}
const auto panel = Q::TextPanel | section | state;
const auto text = Q::Text | section | state;
panelColor = rgbSolid( panelColor, pal.background.solid.base );
setGradient( panel, panelColor );
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
setColor( text, textColor );
}
}
void Editor::setupTextAreaMetrics()
{
using Q = QskTextArea;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
setupTextControlMetrics< Q >();
}
void Editor::setupTextAreaColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
setupTextControlColors< QskTextArea, QskTextAreaSkinlet >( section, theme );
}
void Editor::setupTextFieldMetrics()
{
using Q = QskTextField;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
// =============
setupTextControlMetrics< Q >();
setStrutSize( Q::TextPanel, { -1, 30_px } );
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
setBoxBorderMetrics( Q::TextPanel, 1_px );
for( const auto& state : { Q::Focused, Q::Editing } )
setBoxBorderMetrics( Q::TextPanel | state, { 1_px, 1_px, 1_px, 2_px } );
setBoxShape( Q::TextPanel, 3_px );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
setFontRole( Q::Placeholder, fontRole( Q::Text ) );
}
void Editor::setupTextFieldColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
setupTextControlColors< QskTextField, QskTextFieldSkinlet >( section, theme );
}
using A = QskAspect;
using Q = QskTextField;
const auto& pal = theme.palette;
setColor( Q::TextPanel | Q::Selected, pal.fillColor.accent.selectedTextBackground );
setColor( Q::Placeholder, pal.fillColor.text.secondary );
for( const auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Editing, Q::Disabled } )
{
QRgb panelColor, borderColor1, borderColor2;
if ( state == A::NoState )
{
panelColor = pal.fillColor.control.defaultColor;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.elevation.textControl.border[1];
}
else if ( state == Q::Hovered )
{
panelColor = pal.fillColor.control.secondary;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.elevation.textControl.border[1];
}
else if ( ( state == Q::Focused ) || ( state == Q::Editing ) )
{
panelColor = pal.fillColor.control.inputActive;
borderColor1 = pal.elevation.textControl.border[0];
borderColor2 = pal.fillColor.accent.defaultColor;
}
else if ( state == Q::Disabled )
{
panelColor = pal.fillColor.control.disabled;
borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor;
}
const auto panel = Q::TextPanel | section | state;
panelColor = rgbSolid( panelColor, pal.background.solid.base );
setGradient( panel, panelColor );
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
}
}
void Editor::setupSwitchButtonMetrics()
{
using Q = QskSwitchButton;

View File

@ -43,9 +43,7 @@
#include <QskTabButton.h>
#include <QskTabView.h>
#include <QskTextArea.h>
#include <QskTextAreaSkinlet.h>
#include <QskTextField.h>
#include <QskTextFieldSkinlet.h>
#include <QskTextLabel.h>
#include <QskVirtualKeyboard.h>
@ -145,8 +143,7 @@ namespace
Q_INVOKABLE void setupTabBar();
Q_INVOKABLE void setupTabView();
template< typename Q, typename SK >
void setupTextControl();
Q_INVOKABLE void setupTextInput();
Q_INVOKABLE void setupTextArea();
Q_INVOKABLE void setupTextField();
Q_INVOKABLE void setupTextLabel();
@ -389,9 +386,29 @@ void Editor::setupTextLabel()
setBoxBorderColors( Q::Panel, QskRgb::lighter( m_pal.outline, 108 ) );
}
template< typename Q, typename SK >
void Editor::setupTextControl()
void Editor::setupTextInput()
{
using Q = QskAbstractTextInput;
using A = QskAspect;
using P = QPalette;
for ( auto state : { A::NoState, Q::Disabled } )
{
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
setColor( Q::Text | Q::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
}
}
void Editor::setupTextArea()
{
using Q = QskTextArea;
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
// ========
using A = QskAspect;
using P = QPalette;
@ -400,10 +417,8 @@ void Editor::setupTextControl()
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
setColor( Q::TextPanel | state, m_pal.color( colorGroup, P::Base ) );
setColor( Q::TextPanel | SK::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
setColor( Q::TextPanel | Q::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
setColor( Q::Text | SK::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
setColor( Q::Placeholder, m_pal.color( colorGroup, P::PlaceholderText ) );
}
@ -420,26 +435,38 @@ void Editor::setupTextControl()
setPadding( Q::TextPanel, 4_px );
}
void Editor::setupTextArea()
{
using Q = QskTextArea;
using SK = QskTextAreaSkinlet;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
setupTextControl< Q, SK >();
}
void Editor::setupTextField()
{
using Q = QskTextField;
using SK = QskTextFieldSkinlet;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
setupTextControl< Q, SK >();
// ===
using A = QskAspect;
using P = QPalette;
for ( auto state : { A::NoState, Q::Disabled } )
{
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
setColor( Q::TextPanel | state, m_pal.color( colorGroup, P::Base ) );
setColor( Q::TextPanel | Q::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
setColor( Q::Placeholder, m_pal.color( colorGroup, P::PlaceholderText ) );
}
setColor( Q::TextPanel | Q::ReadOnly, m_pal.disabled( P::Base ) );
setBoxBorderMetrics( Q::TextPanel, 1_px );
setBoxBorderColors( Q::TextPanel, m_pal.outline );
#ifdef SHOW_FOCUS
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.highlightedOutline );
#endif
setBoxShape( Q::TextPanel, 2_px );
setPadding( Q::TextPanel, 4_px );
}
void Editor::setupProgressBar()

View File

@ -12,7 +12,6 @@
#include "QskMaterial3ProgressBarSkinlet.h"
#include "QskMaterial3SliderSkinlet.h"
#include "QskMaterial3TextFieldSkinlet.h"
#include <QskTextEditSkinlet.h>
#include <QskSkinHintTableEditor.h>
@ -188,8 +187,7 @@ namespace
Q_INVOKABLE void setupTabBar();
Q_INVOKABLE void setupTabView();
template< typename Q, typename SK >
void setupTextControl();
Q_INVOKABLE void setupTextInput();
Q_INVOKABLE void setupTextArea();
Q_INVOKABLE void setupTextField();
Q_INVOKABLE void setupTextLabel();
@ -437,13 +435,64 @@ void Editor::setupTextLabel()
setPadding( Q::Panel, 5_px );
}
template< typename Q, typename SK >
void Editor::setupTextControl()
void Editor::setupTextInput()
{
using Q = QskAbstractTextInput;
setColor( Q::Text, m_pal.onSurface );
setFontRole( Q::Text, BodyLarge );
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
}
void Editor::setupTextArea()
{
using Q = QskTextArea;
// ==========
setStrutSize( Q::Panel, -1.0, 56_px );
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
setGradient( Q::Panel, m_pal.surfaceVariant );
setColor( Q::TextPanel | SK::Selected, m_pal.primary12 );
setColor( Q::TextPanel | Q::Selected, m_pal.primary12 );
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
setSpacing( Q::Panel, 8_px );
const auto hoverColor = flattenedColor( m_pal.onSurfaceVariant,
m_pal.surfaceVariant, m_pal.hoverOpacity );
setGradient( Q::Panel | Q::Hovered, hoverColor );
const auto focusColor = flattenedColor( m_pal.onSurfaceVariant,
m_pal.surfaceVariant, m_pal.focusOpacity );
setGradient( Q::Panel | Q::Focused, focusColor );
// ### Also add a pressed state
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
const auto disabledPanelColor = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
setGradient( Q::Panel | Q::Disabled, disabledPanelColor );
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface38 );
// PlaceholderText
setColor( Q::Placeholder, color( Q::Text ) );
setFontRole( Q::Placeholder, BodyLarge );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
}
void Editor::setupTextField()
{
using Q = QskTextField;
// ===
setStrutSize( Q::Panel, -1.0, 56_px );
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
setGradient( Q::Panel, m_pal.surfaceVariant );
setColor( Q::TextPanel | Q::Selected, m_pal.primary12 );
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
@ -459,7 +508,6 @@ void Editor::setupTextControl()
// ### Also add a pressed state
setColor( Q::Text, m_pal.onSurface );
setFontRole( Q::Text, BodyLarge );
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
@ -468,33 +516,11 @@ void Editor::setupTextControl()
setGradient( Q::Panel | Q::Disabled, disabledPanelColor );
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface38 );
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
// PlaceholderText
setColor( Q::Placeholder, color( Q::Text ) );
setFontRole( Q::Placeholder, BodyLarge );
setAlignment( Q::Placeholder, alignment( Q::Text ) );
}
void Editor::setupTextArea()
{
using Q = QskTextArea;
using SK = QskTextEditSkinlet;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
setupTextControl< Q, SK >();
}
void Editor::setupTextField()
{
using Q = QskTextField;
using SK = QskTextInputSkinlet;
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
setupTextControl< Q, SK >();
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
}
void Editor::setupProgressBar()

View File

@ -197,6 +197,7 @@ endif()
list(APPEND HEADERS
controls/QskAbstractButton.h
controls/QskAbstractTextInput.h
controls/QskAnimationHint.h
controls/QskAnimator.h
controls/QskMainView.h
@ -306,6 +307,7 @@ list(APPEND PRIVATE_HEADERS
list(APPEND SOURCES
controls/QskAbstractButton.cpp
controls/QskAbstractTextInput.cpp
controls/QskAnimator.cpp
controls/QskAnimationHint.cpp
controls/QskMainView.cpp

View File

@ -0,0 +1,616 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskAbstractTextInput.h"
#include "QskFontRole.h"
#include "QskQuick.h"
#include "QskEvent.h"
#include "QskInternalMacros.h"
QSK_QT_PRIVATE_BEGIN
#include <private/qquicktextedit_p.h>
#include <private/qquicktextinput_p.h>
#include <private/qquicktextinput_p_p.h>
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
#include <private/qeventpoint_p.h>
#endif
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskAbstractTextInput, Text )
QSK_SYSTEM_STATE( QskAbstractTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Editing, QskAspect::FirstSystemState << 2 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Selected, QskAspect::FirstSystemState << 3 )
static inline void qskUpdateInputMethodFont( const QskAbstractTextInput* input )
{
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
qskUpdateInputMethod( input, queries );
}
static inline QVariant qskInputMethodQuery(
const QQuickItem* item, Qt::InputMethodQuery query, QVariant argument )
{
if ( auto input = qobject_cast< const QQuickTextInput* >( item ) )
return input->inputMethodQuery( query, argument );
if ( auto edit = qobject_cast< const QQuickTextEdit* >( item ) )
return edit->inputMethodQuery( query, argument );
return QVariant();
}
static inline Qt::InputMethodHints qskInputMethodHints( const QQuickItem* item )
{
if ( auto input = qobject_cast< const QQuickTextInput* >( item ) )
return input->inputMethodHints();
if ( auto edit = qobject_cast< const QQuickTextEdit* >( item ) )
return edit->inputMethodHints();
return Qt::InputMethodHints();
}
static inline void qskSetInputMethodHints(
QQuickItem* item, Qt::InputMethodHints hints )
{
if ( auto input = qobject_cast< QQuickTextInput* >( item ) )
input->setInputMethodHints( hints );
else if ( auto edit = qobject_cast< QQuickTextEdit* >( item ) )
edit->setInputMethodHints( hints );
}
inline void qskSetAlignment( QQuickItem* item, Qt::Alignment alignment )
{
item->setProperty( "horizontalAlignment", int( alignment ) & 0x0f );
item->setProperty( "verticalAlignment", int( alignment ) & 0xf0 );
}
static inline void qskTranslateMouseEventPosition(
QMouseEvent* mouseEvent, const QPointF& offset )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
auto& point = mouseEvent->point(0);
QMutableEventPoint::setPosition(
point, point.position() + offset );
#else
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
#endif
}
static inline void qskForwardEvent( QQuickItem* item, QEvent* event )
{
switch( static_cast< int >( event->type() ) )
{
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
{
const auto pos = item->position();
auto mouseEvent = static_cast< QMouseEvent* >( event );
/*
As the event was sent for the parent item
we have to translate the position into
our coordinate system.
*/
qskTranslateMouseEventPosition( mouseEvent, -pos );
QMetaObject::invokeMethod( item, "handleEvent",
Qt::DirectConnection, Q_ARG( QEvent*, event ) );
qskTranslateMouseEventPosition( mouseEvent, pos );
break;
}
default:
QMetaObject::invokeMethod( item, "handleEvent",
Qt::DirectConnection, Q_ARG( QEvent*, event ) );
}
}
class QskAbstractTextInput::PrivateData
{
public:
ActivationModes activationModes;
};
QskAbstractTextInput::QskAbstractTextInput( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
setPolishOnResize( true );
setAcceptHoverEvents( true );
setFocusPolicy( Qt::StrongFocus );
setFlag( QQuickItem::ItemAcceptsInputMethod );
}
QskAbstractTextInput::~QskAbstractTextInput()
{
}
QskAbstractTextInput::ActivationModes QskAbstractTextInput::activationModes() const
{
return m_data->activationModes;
}
void QskAbstractTextInput::setActivationModes( ActivationModes modes )
{
if ( m_data->activationModes != modes )
{
m_data->activationModes = modes;
Q_EMIT activationModesChanged();
}
}
bool QskAbstractTextInput::selectByMouse() const
{
return wrappedInput()->property( "selectByMouse" ).value< bool >();
}
void QskAbstractTextInput::setSelectByMouse( bool on )
{
wrappedInput()->setProperty( "selectByMouse", on );
}
QString QskAbstractTextInput::text() const
{
return wrappedInput()->property( "text" ).value< QString >();
}
void QskAbstractTextInput::setText( const QString& text )
{
wrappedInput()->setProperty( "text", text );
}
QString QskAbstractTextInput::preeditText() const
{
return wrappedInput()->property( "preeditText" ).value< QString >();
}
void QskAbstractTextInput::clear()
{
QMetaObject::invokeMethod( wrappedInput(), "clear" );
}
void QskAbstractTextInput::selectAll()
{
QMetaObject::invokeMethod( wrappedInput(), "selectAll" );
}
void QskAbstractTextInput::deselect()
{
QMetaObject::invokeMethod( wrappedInput(), "deselect" );
}
bool QskAbstractTextInput::canUndo() const
{
return wrappedInput()->property( "canUndo" ).value< bool >();
}
bool QskAbstractTextInput::canRedo() const
{
return wrappedInput()->property( "canRedo" ).value< bool >();
}
void QskAbstractTextInput::setFontRole( const QskFontRole& role )
{
if ( setFontRoleHint( Text, role ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
void QskAbstractTextInput::resetFontRole()
{
if ( resetFontRoleHint( Text ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
QskFontRole QskAbstractTextInput::fontRole() const
{
return fontRoleHint( Text );
}
QFont QskAbstractTextInput::font() const
{
return effectiveFont( Text );
}
QVariant QskAbstractTextInput::inputMethodQuery(
Qt::InputMethodQuery property ) const
{
return inputMethodQuery( property, QVariant() );
}
QVariant QskAbstractTextInput::inputMethodQuery(
Qt::InputMethodQuery query, const QVariant& argument ) const
{
switch ( query )
{
case Qt::ImEnabled:
{
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
}
case Qt::ImFont:
{
return font();
}
case Qt::ImPreferredLanguage:
{
return locale();
}
case Qt::ImInputItemClipRectangle:
case Qt::ImCursorRectangle:
{
QVariant v = qskInputMethodQuery( wrappedInput(), query, argument );
#if 1
if ( v.canConvert< QRectF >() )
v.setValue( v.toRectF().translated( wrappedInput()->position() ) );
#endif
return v;
}
default:
{
return qskInputMethodQuery( wrappedInput(), query, argument );
}
}
}
Qt::InputMethodHints QskAbstractTextInput::inputMethodHints() const
{
return qskInputMethodHints( wrappedInput() );
}
void QskAbstractTextInput::setInputMethodHints( Qt::InputMethodHints hints )
{
if ( qskInputMethodHints( wrappedInput() ) != hints )
{
qskSetInputMethodHints( wrappedInput(), hints );
qskUpdateInputMethod( this, Qt::ImHints );
}
}
bool QskAbstractTextInput::event( QEvent* event )
{
if ( event->type() == QEvent::LocaleChange )
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
if ( event->type() == QEvent::ShortcutOverride )
{
forwardEvent( event );
return event->isAccepted();
}
return Inherited::event( event );
}
void QskAbstractTextInput::mousePressEvent( QMouseEvent* event )
{
forwardEvent( event );
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskAbstractTextInput::mouseMoveEvent( QMouseEvent* event )
{
forwardEvent( event );
}
void QskAbstractTextInput::mouseReleaseEvent( QMouseEvent* event )
{
forwardEvent( event );
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskAbstractTextInput::mouseDoubleClickEvent( QMouseEvent* event )
{
forwardEvent( event );
}
void QskAbstractTextInput::keyPressEvent( QKeyEvent* event )
{
if ( isEditing() )
{
switch ( event->key() )
{
case Qt::Key_Escape:
{
setEditing( false );
break;
}
case Qt::Key_Enter:
case Qt::Key_Return:
{
const auto hints = inputMethodQuery( Qt::ImHints ).toInt();
if ( !( hints & Qt::ImhMultiLine ) )
{
if ( acceptInput() )
{
QGuiApplication::inputMethod()->commit();
setEditing( false );
}
}
break;
}
}
if ( isEditing() )
{
forwardEvent( event );
}
else
{
// When returning from a virtual keyboard
qskForceActiveFocus( this, Qt::PopupFocusReason );
}
}
else
{
if ( ( activationModes() & ActivationOnKey ) && !event->isAutoRepeat() )
{
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
{
setEditing( true );
return;
}
}
Inherited::keyPressEvent( event );
}
}
void QskAbstractTextInput::keyReleaseEvent( QKeyEvent* event )
{
Inherited::keyReleaseEvent( event );
}
void QskAbstractTextInput::focusInEvent( QFocusEvent* event )
{
if ( activationModes() & ActivationOnFocus )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
break;
default:
#if 1
// auto selecting the complete text ???
#endif
setEditing( true );
}
}
Inherited::focusInEvent( event );
}
void QskAbstractTextInput::focusOutEvent( QFocusEvent* event )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
{
break;
}
default:
{
deselect();
setEditing( false );
}
}
Inherited::focusOutEvent( event );
}
void QskAbstractTextInput::inputMethodEvent( QInputMethodEvent* event )
{
const bool hadCursor = isCursorVisible();
forwardEvent( event );
if ( isCursorVisible() && !hadCursor )
{
/*
The initial InputMethod events might be sent from the
platform depending on focus. Unfortunately an
empty dummy event ( = no attributes ) leads to showing
the cursor.
*/
if ( isEditing() )
setCursorVisible( false );
}
}
bool QskAbstractTextInput::isReadOnly() const
{
return wrappedInput()->property( "readOnly" ).value< bool >();
}
void QskAbstractTextInput::setReadOnly( bool on )
{
if ( on == isReadOnly() )
return;
#if 1
// do we want to be able to restore the previous policy ?
setFocusPolicy( Qt::NoFocus );
#endif
auto input = wrappedInput();
input->setProperty( "readOnly", on );
// we are killing user settings here ?
input->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
qskUpdateInputMethod( this, Qt::ImReadOnly );
#else
qskUpdateInputMethod( this, Qt::ImEnabled );
#endif
setSkinStateFlag( ReadOnly, on );
}
bool QskAbstractTextInput::isEditing() const
{
return hasSkinState( Editing );
}
void QskAbstractTextInput::setEditing( bool on )
{
if ( isReadOnly() || on == isEditing() )
return;
setSkinStateFlag( Editing, on );
auto input = wrappedInput();
if ( input->property( "cursorVisible" ).value< bool >() != on )
{
input->setProperty( "cursorVisible", on );
if ( auto textInput = qobject_cast< QQuickTextInput* >( input ) )
{
auto d = QQuickTextInputPrivate::get( textInput );
d->setBlinkingCursorEnabled( on );
if ( !on )
{
if ( d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive() )
d->updatePasswordEchoEditing( false );
}
}
input->polish();
input->update();
}
if ( !on && acceptInput() )
QMetaObject::invokeMethod( input, "editingFinished" );
qskInputMethodSetVisible( this, on );
Q_EMIT editingChanged( on );
}
bool QskAbstractTextInput::acceptInput()
{
return true;
}
bool QskAbstractTextInput::overwriteMode() const
{
return wrappedInput()->property( "overwriteMode" ).value< bool >();
}
void QskAbstractTextInput::setOverwriteMode( bool overwrite )
{
wrappedInput()->setProperty( "overwriteMode", overwrite );
}
int QskAbstractTextInput::cursorPosition() const
{
return wrappedInput()->property( "cursorPosition" ).value< int >();
}
void QskAbstractTextInput::setCursorPosition( int pos )
{
wrappedInput()->setProperty( "cursorPosition", pos );
}
bool QskAbstractTextInput::isCursorVisible() const
{
return wrappedInput()->property( "cursorVisible" ).value< bool >();
}
void QskAbstractTextInput::setCursorVisible( bool on )
{
wrappedInput()->setProperty( "cursorVisible", on );
}
void QskAbstractTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
{
wrappedInput()->setProperty( "wrapMode", static_cast< int >( wrapMode ) );
}
QskTextOptions::WrapMode QskAbstractTextInput::wrapMode() const
{
const auto mode = wrappedInput()->property( "wrapMode" ).value< int >();
return static_cast< QskTextOptions::WrapMode >( mode );
}
void QskAbstractTextInput::setAlignment( Qt::Alignment alignment )
{
if ( setAlignmentHint( Text, alignment ) )
{
qskSetAlignment( wrappedInput(), alignment );
Q_EMIT alignmentChanged();
}
}
void QskAbstractTextInput::resetAlignment()
{
if ( resetAlignmentHint( Text ) )
{
qskSetAlignment( wrappedInput(), alignment() );
Q_EMIT alignmentChanged();
}
}
Qt::Alignment QskAbstractTextInput::alignment() const
{
Qt::Alignment alignment = Qt::AlignLeft;
if ( qobject_cast< const QQuickTextEdit* >( wrappedInput() ) )
alignment |= Qt::AlignTop;
else
alignment |= Qt::AlignVCenter;
return alignmentHint( Text, alignment );
}
void QskAbstractTextInput::updateLayout()
{
QMetaObject::invokeMethod( wrappedInput(), "updateMetrics" );
qskSetItemGeometry( wrappedInput(), subControlRect( Text ) );
}
void QskAbstractTextInput::updateNode( QSGNode* node )
{
QMetaObject::invokeMethod( wrappedInput(), "updateColors" );
Inherited::updateNode( node );
}
const QQuickItem* QskAbstractTextInput::wrappedInput() const
{
auto that = const_cast< QskAbstractTextInput* >( this );
return that->wrappedInput();
}
void QskAbstractTextInput::forwardEvent( QEvent* event )
{
qskForwardEvent( wrappedInput(), event );
}
#include "moc_QskAbstractTextInput.cpp"

View File

@ -0,0 +1,194 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_ABSTRACT_TEXT_INPUT_H
#define QSK_ABSTRACT_TEXT_INPUT_H
#include "QskControl.h"
#include "QskTextOptions.h"
class QskFontRole;
class QSK_EXPORT QskAbstractTextInput : public QskControl
{
Q_OBJECT
Q_PROPERTY( QString text READ text
WRITE setText NOTIFY textChanged USER true )
Q_PROPERTY( QString preeditText READ preeditText
NOTIFY preeditTextChanged )
Q_PROPERTY( bool editing READ isEditing
WRITE setEditing NOTIFY editingChanged )
Q_PROPERTY( bool readOnly READ isReadOnly
WRITE setReadOnly NOTIFY readOnlyChanged )
Q_PROPERTY( ActivationModes activationModes READ activationModes
WRITE setActivationModes NOTIFY activationModesChanged )
Q_PROPERTY( QskFontRole fontRole READ fontRole
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
Q_PROPERTY( QFont font READ font )
Q_PROPERTY( bool overwriteMode READ overwriteMode
WRITE setOverwriteMode NOTIFY overwriteModeChanged )
Q_PROPERTY( bool cursorVisible READ isCursorVisible
WRITE setCursorVisible NOTIFY cursorVisibleChanged )
Q_PROPERTY( int cursorPosition READ cursorPosition
WRITE setCursorPosition NOTIFY cursorPositionChanged )
Q_PROPERTY( Qt::Alignment alignment READ alignment
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
WRITE setWrapMode NOTIFY wrapModeChanged )
Q_PROPERTY( bool selectByMouse READ selectByMouse
WRITE setSelectByMouse NOTIFY selectByMouseChanged )
Q_PROPERTY( bool canUndo READ canUndo NOTIFY canUndoChanged )
Q_PROPERTY( bool canRedo READ canRedo NOTIFY canRedoChanged )
using Inherited = QskControl;
public:
QSK_SUBCONTROLS( Text )
QSK_STATES( ReadOnly, Editing, Selected )
enum ActivationMode
{
NoActivation,
ActivationOnFocus = 1 << 0,
ActivationOnMouse = 1 << 1,
ActivationOnKey = 1 << 2,
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
};
Q_ENUM( ActivationMode )
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
~QskAbstractTextInput() override;
QString text() const;
QString preeditText() const;
bool isReadOnly() const;
void setReadOnly( bool );
bool isEditing() const;
void setActivationModes( ActivationModes );
ActivationModes activationModes() const;
void setSelectByMouse( bool );
bool selectByMouse() const;
void setAlignment( Qt::Alignment );
void resetAlignment();
Qt::Alignment alignment() const;
void setWrapMode( QskTextOptions::WrapMode );
QskTextOptions::WrapMode wrapMode() const;
void setFontRole( const QskFontRole& role );
void resetFontRole();
QskFontRole fontRole() const;
QFont font() const;
bool overwriteMode() const;
void setOverwriteMode( bool );
bool isCursorVisible() const;
void setCursorVisible( bool );
int cursorPosition() const;
void setCursorPosition( int );
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& ) const;
Qt::InputMethodHints inputMethodHints() const;
void setInputMethodHints( Qt::InputMethodHints );
bool canUndo() const;
bool canRedo() const;
public Q_SLOTS:
void setText( const QString& );
void setEditing( bool );
void clear();
void deselect();
void selectAll();
Q_SIGNALS:
void editingChanged( bool );
void readOnlyChanged( bool );
void activationModesChanged();
void fontRoleChanged();
void overwriteModeChanged( bool );
void cursorPositionChanged( int );
void cursorVisibleChanged( bool );
void selectByMouseChanged( bool );
void wrapModeChanged( QskTextOptions::WrapMode );
void alignmentChanged();
void textChanged( const QString& );
void textEdited( const QString& );
void displayTextChanged( const QString& );
void preeditTextChanged( const QString& );
#if 1
void canUndoChanged( bool );
void canRedoChanged( bool );
#endif
protected:
QskAbstractTextInput( QQuickItem* parent = nullptr );
virtual QQuickItem* wrappedInput() = 0;
const QQuickItem* wrappedInput() const;
void forwardEvent( QEvent* );
bool event( QEvent* ) override;
void mousePressEvent( QMouseEvent* ) override;
void mouseMoveEvent( QMouseEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override;
void mouseDoubleClickEvent( QMouseEvent* ) override;
void keyPressEvent( QKeyEvent* ) override;
void keyReleaseEvent( QKeyEvent* ) override;
void focusInEvent( QFocusEvent* ) override;
void focusOutEvent( QFocusEvent* ) override;
void inputMethodEvent( QInputMethodEvent* ) override;
virtual bool acceptInput();
void updateLayout() override;
void updateNode( QSGNode* ) override;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QskAbstractTextInput::ActivationModes )
Q_DECLARE_METATYPE( QskAbstractTextInput::ActivationModes )
#endif

View File

@ -12,19 +12,9 @@
QSK_QT_PRIVATE_BEGIN
#include <private/qquicktextedit_p.h>
#include <private/qquicktextedit_p_p.h>
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
#include <private/qeventpoint_p.h>
#endif
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskTextEdit, TextPanel )
QSK_SUBCONTROL( QskTextEdit, Text )
QSK_SYSTEM_STATE( QskTextEdit, ReadOnly, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskTextEdit, Editing, QskAspect::FirstSystemState << 2 )
QSK_SYSTEM_STATE( QskTextEdit, Error, QskAspect::FirstSystemState << 4 )
static inline void qskPropagateReadOnly( QskTextEdit* edit )
{
@ -34,19 +24,6 @@ static inline void qskPropagateReadOnly( QskTextEdit* edit )
QCoreApplication::sendEvent( edit, &event );
}
static inline void qskTranslateMouseEventPosition(
QMouseEvent* mouseEvent, const QPointF& offset )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
auto& point = mouseEvent->point( 0 );
QMutableEventPoint::setPosition(
point, point.position() + offset );
#else
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
#endif
}
static inline void qskBindSignals(
const QQuickTextEdit* wrappedEdit, QskTextEdit* edit )
{
@ -62,6 +39,9 @@ static inline void qskBindSignals(
QObject::connect( wrappedEdit, &QQuickTextEdit::overwriteModeChanged,
edit, &QskTextEdit::overwriteModeChanged );
QObject::connect( wrappedEdit, &QQuickTextEdit::cursorPositionChanged,
edit, [ edit ] { Q_EMIT edit->cursorPositionChanged( edit->cursorPosition() ); } );
QObject::connect( wrappedEdit, &QQuickTextEdit::wrapModeChanged,
edit, [ edit ] { Q_EMIT edit->wrapModeChanged( edit->wrapMode() ); } );
@ -92,57 +72,22 @@ namespace
{
class QuickTextEdit final : public QQuickTextEdit
{
Q_OBJECT
using Inherited = QQuickTextEdit;
public:
QuickTextEdit( QskTextEdit* );
void setEditing( bool on );
inline void setAlignment( Qt::Alignment alignment )
{
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
setVAlign( ( VAlignment ) ( int( alignment ) & 0xf0 ) );
}
void updateColors();
void updateMetrics();
inline bool handleEvent( QEvent* event )
{
bool ok;
switch( static_cast< int >( event->type() ) )
{
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
{
auto mouseEvent = static_cast< QMouseEvent* >( event );
/*
As the event was sent for the parent item
we have to translate the position into
our coordinate system.
*/
qskTranslateMouseEventPosition( mouseEvent, -position() );
ok = this->event( mouseEvent );
qskTranslateMouseEventPosition( mouseEvent, position() );
break;
}
default:
ok = this->event( event );
}
return ok;
}
inline bool hasSelectedText() const
{
return !selectedText().isEmpty();
}
Q_INVOKABLE void updateColors();
Q_INVOKABLE void updateMetrics();
Q_INVOKABLE void handleEvent( QEvent* ev ) { event( ev ); }
protected:
@ -192,19 +137,6 @@ namespace
this, &QuickTextEdit::updateClip );
}
void QuickTextEdit::setEditing( bool on )
{
auto d = QQuickTextEditPrivate::get( this );
if ( d->cursorVisible == on )
return;
setCursorVisible( on );
polish();
update();
}
void QuickTextEdit::updateMetrics()
{
auto textEdit = static_cast< const QskTextEdit* >( parentItem() );
@ -221,7 +153,7 @@ namespace
setColor( input->color( Q::Text ) );
const auto state = QskTextEditSkinlet::Selected;
const auto state = QskTextEdit::Selected;
setSelectionColor( input->color( Q::TextPanel | state ) );
setSelectedTextColor( input->color( Q::Text | state ) );
@ -232,23 +164,12 @@ class QskTextEdit::PrivateData
{
public:
QuickTextEdit* wrappedEdit;
ActivationModes activationModes;
};
QskTextEdit::QskTextEdit( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
setPolishOnResize( true );
setAcceptHoverEvents( true );
setFocusPolicy( Qt::StrongFocus );
setFlag( QQuickItem::ItemAcceptsInputMethod );
/*
QQuickTextEdit is a beast of almost 3.5k lines of code, we don't
want to reimplement that - at least not now.
@ -269,341 +190,6 @@ QskTextEdit::~QskTextEdit()
{
}
bool QskTextEdit::event( QEvent* event )
{
if ( event->type() == QEvent::ShortcutOverride )
{
return m_data->wrappedEdit->handleEvent( event );
}
else if ( event->type() == QEvent::LocaleChange )
{
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
}
return Inherited::event( event );
}
void QskTextEdit::keyPressEvent( QKeyEvent* event )
{
if ( isEditing() )
{
switch ( event->key() )
{
#if 1
case Qt::Key_Escape:
{
setEditing( false );
qskForceActiveFocus( this, Qt::PopupFocusReason );
break;
}
#endif
default:
{
m_data->wrappedEdit->handleEvent( event );
}
}
return;
}
if ( ( m_data->activationModes & ActivationOnKey ) && !event->isAutoRepeat() )
{
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
{
setEditing( true );
return;
}
}
Inherited::keyPressEvent( event );
}
void QskTextEdit::keyReleaseEvent( QKeyEvent* event )
{
Inherited::keyReleaseEvent( event );
}
void QskTextEdit::mousePressEvent( QMouseEvent* event )
{
m_data->wrappedEdit->handleEvent( event );
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskTextEdit::mouseMoveEvent( QMouseEvent* event )
{
m_data->wrappedEdit->handleEvent( event );
}
void QskTextEdit::mouseReleaseEvent( QMouseEvent* event )
{
m_data->wrappedEdit->handleEvent( event );
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskTextEdit::mouseDoubleClickEvent( QMouseEvent* event )
{
m_data->wrappedEdit->handleEvent( event );
}
void QskTextEdit::inputMethodEvent( QInputMethodEvent* event )
{
m_data->wrappedEdit->handleEvent( event );
}
void QskTextEdit::focusInEvent( QFocusEvent* event )
{
if ( m_data->activationModes & ActivationOnFocus )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
break;
default:
#if 1
// auto selecting the complete text ???
#endif
setEditing( true );
}
}
Inherited::focusInEvent( event );
}
void QskTextEdit::focusOutEvent( QFocusEvent* event )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
{
break;
}
default:
{
m_data->wrappedEdit->deselect();
setEditing( false );
}
}
Inherited::focusOutEvent( event );
}
void QskTextEdit::updateLayout()
{
m_data->wrappedEdit->updateMetrics();
qskSetItemGeometry( m_data->wrappedEdit, subControlRect( Text ) );
}
void QskTextEdit::updateNode( QSGNode* node )
{
m_data->wrappedEdit->updateColors();
Inherited::updateNode( node );
}
QString QskTextEdit::text() const
{
return m_data->wrappedEdit->text();
}
void QskTextEdit::setText( const QString& text )
{
m_data->wrappedEdit->setText( text );
}
void QskTextEdit::clear()
{
m_data->wrappedEdit->clear();
}
void QskTextEdit::selectAll()
{
m_data->wrappedEdit->selectAll();
}
QskTextEdit::ActivationModes QskTextEdit::activationModes() const
{
return static_cast< QskTextEdit::ActivationModes >( m_data->activationModes );
}
void QskTextEdit::setActivationModes( ActivationModes modes )
{
if ( static_cast< ActivationModes >( m_data->activationModes ) != modes )
{
m_data->activationModes = modes;
Q_EMIT activationModesChanged();
}
}
static inline void qskUpdateInputMethodFont( const QskTextEdit* input )
{
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
qskUpdateInputMethod( input, queries );
}
void QskTextEdit::setFontRole( const QskFontRole& role )
{
if ( setFontRoleHint( Text, role ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
void QskTextEdit::resetFontRole()
{
if ( resetFontRoleHint( Text ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
QskFontRole QskTextEdit::fontRole() const
{
return fontRoleHint( Text );
}
void QskTextEdit::setAlignment( Qt::Alignment alignment )
{
if ( setAlignmentHint( Text, alignment ) )
{
m_data->wrappedEdit->setAlignment( alignment );
Q_EMIT alignmentChanged();
}
}
void QskTextEdit::resetAlignment()
{
if ( resetAlignmentHint( Text ) )
{
m_data->wrappedEdit->setAlignment( alignment() );
Q_EMIT alignmentChanged();
}
}
Qt::Alignment QskTextEdit::alignment() const
{
return alignmentHint( Text, Qt::AlignLeft | Qt::AlignTop );
}
void QskTextEdit::setWrapMode( QskTextOptions::WrapMode wrapMode )
{
m_data->wrappedEdit->setWrapMode(
static_cast< QQuickTextEdit::WrapMode >( wrapMode ) );
}
QskTextOptions::WrapMode QskTextEdit::wrapMode() const
{
return static_cast< QskTextOptions::WrapMode >(
m_data->wrappedEdit->wrapMode() );
}
void QskTextEdit::setSelectByMouse( bool on )
{
m_data->wrappedEdit->setSelectByMouse( on );
}
bool QskTextEdit::selectByMouse() const
{
return m_data->wrappedEdit->selectByMouse();
}
QFont QskTextEdit::font() const
{
return effectiveFont( QskTextEdit::Text );
}
bool QskTextEdit::isReadOnly() const
{
return m_data->wrappedEdit->isReadOnly();
}
void QskTextEdit::setReadOnly( bool on )
{
auto edit = m_data->wrappedEdit;
if ( edit->isReadOnly() == on )
return;
#if 1
// do we want to be able to restore the previous policy ?
setFocusPolicy( Qt::NoFocus );
#endif
edit->setReadOnly( on );
// we are killing user settings here ?
edit->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
qskUpdateInputMethod( this, Qt::ImEnabled );
setSkinStateFlag( ReadOnly, on );
}
void QskTextEdit::setEditing( bool on )
{
if ( isReadOnly() || on == isEditing() )
return;
setSkinStateFlag( Editing, on );
m_data->wrappedEdit->setEditing( on );
if ( on )
{
#if 0
updateInputMethod( Qt::ImCursorRectangle | Qt::ImAnchorRectangle );
QGuiApplication::inputMethod()->inputDirection
#endif
qskInputMethodSetVisible( this, true );
}
else
{
Q_EMIT m_data->wrappedEdit->editingFinished();
#if 0
inputMethod->reset();
#endif
qskInputMethodSetVisible( this, false );
}
Q_EMIT editingChanged( on );
}
bool QskTextEdit::isEditing() const
{
return hasSkinState( Editing );
}
int QskTextEdit::cursorPosition() const
{
return m_data->wrappedEdit->cursorPosition();
}
void QskTextEdit::setCursorPosition( int pos )
{
m_data->wrappedEdit->setCursorPosition( pos );
}
QString QskTextEdit::preeditText() const
{
return m_data->wrappedEdit->preeditText();
}
bool QskTextEdit::overwriteMode() const
{
return m_data->wrappedEdit->overwriteMode();
}
void QskTextEdit::setOverwriteMode( bool overwrite )
{
m_data->wrappedEdit->setOverwriteMode( overwrite );
}
void QskTextEdit::setTextFormat( QskTextOptions::TextFormat textFormat )
{
m_data->wrappedEdit->setTextFormat(
@ -621,70 +207,6 @@ int QskTextEdit::lineCount() const
return m_data->wrappedEdit->lineCount();
}
QVariant QskTextEdit::inputMethodQuery(
Qt::InputMethodQuery property ) const
{
return inputMethodQuery( property, QVariant() );
}
QVariant QskTextEdit::inputMethodQuery(
Qt::InputMethodQuery query, const QVariant& argument ) const
{
switch ( query )
{
case Qt::ImEnabled:
{
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
}
case Qt::ImFont:
{
return font();
}
case Qt::ImPreferredLanguage:
{
return locale();
}
case Qt::ImInputItemClipRectangle:
case Qt::ImCursorRectangle:
{
QVariant v = m_data->wrappedEdit->inputMethodQuery( query, argument );
#if 1
if ( v.canConvert< QRectF >() )
v.setValue( v.toRectF().translated( m_data->wrappedEdit->position() ) );
#endif
return v;
}
default:
{
return m_data->wrappedEdit->inputMethodQuery( query, argument );
}
}
}
bool QskTextEdit::canUndo() const
{
return m_data->wrappedEdit->canUndo();
}
bool QskTextEdit::canRedo() const
{
return m_data->wrappedEdit->canRedo();
}
Qt::InputMethodHints QskTextEdit::inputMethodHints() const
{
return m_data->wrappedEdit->inputMethodHints();
}
void QskTextEdit::setInputMethodHints( Qt::InputMethodHints hints )
{
if ( m_data->wrappedEdit->inputMethodHints() != hints )
{
m_data->wrappedEdit->setInputMethodHints( hints );
qskUpdateInputMethod( this, Qt::ImHints );
}
}
int QskTextEdit::tabStopDistance() const
{
return m_data->wrappedEdit->tabStopDistance();
@ -741,4 +263,10 @@ void QskTextEdit::setupFrom( const QQuickItem* item )
}
}
QQuickItem* QskTextEdit::wrappedInput()
{
return m_data->wrappedEdit;
}
#include "QskTextEdit.moc"
#include "moc_QskTextEdit.cpp"

View File

@ -6,185 +6,53 @@
#ifndef QSK_TEXT_EDIT_H
#define QSK_TEXT_EDIT_H
#include "QskControl.h"
#include "QskAbstractTextInput.h"
#include "QskTextOptions.h"
class QValidator;
class QskFontRole;
class QSK_EXPORT QskTextEdit : public QskControl
class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
{
Q_OBJECT
Q_PROPERTY( QString text READ text
WRITE setText NOTIFY textChanged USER true )
Q_PROPERTY( QskFontRole fontRole READ fontRole
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
Q_PROPERTY( QFont font READ font )
Q_PROPERTY( Qt::Alignment alignment READ alignment
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
WRITE setWrapMode NOTIFY wrapModeChanged )
Q_PROPERTY( int lineCount READ lineCount NOTIFY lineCountChanged )
Q_PROPERTY( QskTextOptions::TextFormat textFormat READ textFormat
WRITE setTextFormat NOTIFY textFormatChanged )
Q_PROPERTY( ActivationModes activationModes READ activationModes
WRITE setActivationModes NOTIFY activationModesChanged )
Q_PROPERTY( bool selectByMouse READ selectByMouse
WRITE setSelectByMouse NOTIFY selectByMouseChanged )
Q_PROPERTY( bool editing READ isEditing
WRITE setEditing NOTIFY editingChanged )
Q_PROPERTY( qreal tabStopDistance READ tabStopDistance
WRITE setTabStopDistance NOTIFY tabStopDistanceChanged )
using Inherited = QskControl;
using Inherited = QskAbstractTextInput;
public:
QSK_SUBCONTROLS( TextPanel, Text )
QSK_STATES( ReadOnly, Editing, Error )
enum ActivationMode
{
NoActivation,
ActivationOnFocus = 1 << 0,
ActivationOnMouse = 1 << 1,
ActivationOnKey = 1 << 2,
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
};
Q_ENUM( ActivationMode )
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
QSK_SUBCONTROLS( TextPanel )
QskTextEdit( QQuickItem* parent = nullptr );
~QskTextEdit() override;
void setupFrom( const QQuickItem* );
QString text() const;
void setFontRole( const QskFontRole& role );
void resetFontRole();
QskFontRole fontRole() const;
void setAlignment( Qt::Alignment );
void resetAlignment();
Qt::Alignment alignment() const;
void setWrapMode( QskTextOptions::WrapMode );
QskTextOptions::WrapMode wrapMode() const;
void setTextFormat( QskTextOptions::TextFormat );
QskTextOptions::TextFormat textFormat() const;
int lineCount() const;
void setActivationModes( ActivationModes );
ActivationModes activationModes() const;
void setSelectByMouse( bool );
bool selectByMouse() const;
bool isEditing() const;
QFont font() const;
bool isReadOnly() const;
void setReadOnly( bool );
int cursorPosition() const;
void setCursorPosition( int );
QString preeditText() const;
bool overwriteMode() const;
void setOverwriteMode( bool );
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& argument ) const;
bool canUndo() const;
bool canRedo() const;
Qt::InputMethodHints inputMethodHints() const;
void setInputMethodHints( Qt::InputMethodHints );
int tabStopDistance() const;
void setTabStopDistance( qreal );
public Q_SLOTS:
void clear();
void selectAll();
void setText( const QString& );
void setEditing( bool );
Q_SIGNALS:
void textChanged( const QString& );
void preeditTextChanged( const QString& );
void editingChanged( bool );
void activationModesChanged();
void readOnlyChanged( bool );
void panelChanged( bool );
void displayTextChanged( const QString& );
void textEdited( const QString& );
void placeholderTextChanged( const QString& );
void fontRoleChanged();
void alignmentChanged();
void wrapModeChanged( QskTextOptions::WrapMode );
void lineCountChanged( int );
void selectByMouseChanged( bool );
void textFormatChanged( QskTextOptions::TextFormat );
void overwriteModeChanged( bool );
void tabStopDistanceChanged( qreal );
protected:
bool event( QEvent* ) override;
void inputMethodEvent( QInputMethodEvent* ) override;
void focusInEvent( QFocusEvent* ) override;
void focusOutEvent( QFocusEvent* ) override;
void mousePressEvent( QMouseEvent* ) override;
void mouseMoveEvent( QMouseEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override;
void mouseDoubleClickEvent( QMouseEvent* ) override;
void keyPressEvent( QKeyEvent* ) override;
void keyReleaseEvent( QKeyEvent* ) override;
void updateLayout() override;
void updateNode( QSGNode* ) override;
private:
QQuickItem* wrappedInput() override final;
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextEdit::ActivationModes )
Q_DECLARE_METATYPE( QskTextEdit::ActivationModes )
#endif

View File

@ -10,8 +10,6 @@
using Q = QskTextEdit;
QSK_SYSTEM_STATE( QskTextEditSkinlet, Selected, QskAspect::FirstSystemState << 3 )
QskTextEditSkinlet::QskTextEditSkinlet( QskSkin* skin )
: Inherited( skin )
{

View File

@ -13,8 +13,6 @@ class QSK_EXPORT QskTextEditSkinlet : public QskSkinlet
using Inherited = QskSkinlet;
public:
QSK_STATES( Selected )
enum NodeRole : quint8
{
TextPanelRole,

View File

@ -13,17 +13,10 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquicktextinput_p.h>
#include <private/qquicktextinput_p_p.h>
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
#include <private/qeventpoint_p.h>
#endif
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskTextInput, Text )
QSK_SUBCONTROL( QskTextInput, TextPanel )
QSK_SYSTEM_STATE( QskTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskTextInput, Editing, QskAspect::FirstSystemState << 2 )
QSK_SYSTEM_STATE( QskTextInput, Error, QskAspect::FirstSystemState << 4 )
static inline void qskPropagateReadOnly( QskTextInput* input )
@ -34,19 +27,6 @@ static inline void qskPropagateReadOnly( QskTextInput* input )
QCoreApplication::sendEvent( input, &event );
}
static inline void qskTranslateMouseEventPosition(
QMouseEvent* mouseEvent, const QPointF& offset )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
auto& point = mouseEvent->point(0);
QMutableEventPoint::setPosition(
point, point.position() + offset );
#else
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
#endif
}
static inline void qskBindSignals(
const QQuickTextInput* wrappedInput, QskTextInput* input )
{
@ -71,6 +51,9 @@ static inline void qskBindSignals(
QObject::connect( wrappedInput, &QQuickTextInput::overwriteModeChanged,
input, &QskTextInput::overwriteModeChanged );
QObject::connect( wrappedInput, &QQuickTextInput::cursorPositionChanged,
input, [ input ] { Q_EMIT input->cursorPositionChanged( input->cursorPosition() ); } );
QObject::connect( wrappedInput, &QQuickTextInput::maximumLengthChanged,
input, &QskTextInput::maximumLengthChanged );
@ -97,13 +80,13 @@ namespace
{
class QuickTextInput final : public QQuickTextInput
{
Q_OBJECT
using Inherited = QQuickTextInput;
public:
QuickTextInput( QskTextInput* );
void setEditing( bool on );
inline void setAlignment( Qt::Alignment alignment )
{
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
@ -115,60 +98,9 @@ namespace
return QQuickTextInputPrivate::get( this )->fixup();
}
void updateColors();
void updateMetrics();
inline bool handleEvent( QEvent* event )
{
bool ok;
switch( static_cast< int >( event->type() ) )
{
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
{
auto mouseEvent = static_cast< QMouseEvent* >( event );
/*
As the event was sent for the parent item
we have to translate the position into
our coordinate system.
*/
qskTranslateMouseEventPosition( mouseEvent, -position() );
ok = this->event( mouseEvent );
qskTranslateMouseEventPosition( mouseEvent, position() );
break;
}
case QEvent::InputMethod:
{
const bool hadCursor = isCursorVisible();
ok = this->event( event );
if ( isCursorVisible() && !hadCursor )
{
/*
The initial InputMethod events might be sent from the
platform depending on focus. Unfortunately an
empty dummy event ( = no attributes ) leads to showing
the cursor.
*/
auto input = static_cast< const QskTextInput* >( parentItem() );
if ( !input->isEditing() )
setCursorVisible( false );
}
break;
}
default:
ok = this->event( event );
}
return ok;
}
Q_INVOKABLE void updateColors();
Q_INVOKABLE void updateMetrics();
Q_INVOKABLE void handleEvent( QEvent* );
protected:
@ -218,25 +150,6 @@ namespace
this, &QuickTextInput::updateClip );
}
void QuickTextInput::setEditing( bool on )
{
auto d = QQuickTextInputPrivate::get( this );
if ( d->cursorVisible == on )
return;
setCursorVisible( on );
d->setBlinkingCursorEnabled( on );
if ( !on )
{
if ( d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive() )
d->updatePasswordEchoEditing( false );
}
polish();
update();
}
void QuickTextInput::updateMetrics()
{
@ -254,34 +167,29 @@ namespace
setColor( input->color( Q::Text ) );
const auto state = QskTextInputSkinlet::Selected;
const auto state = QskTextInput::Selected;
setSelectionColor( input->color( Q::TextPanel | state ) );
setSelectedTextColor( input->color( Q::Text | state ) );
}
void QuickTextInput::handleEvent( QEvent* ev )
{
event( ev );
}
}
class QskTextInput::PrivateData
{
public:
QuickTextInput* wrappedInput;
ActivationModes activationModes;
};
QskTextInput::QskTextInput( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
setPolishOnResize( true );
setAcceptHoverEvents( true );
setFocusPolicy( Qt::StrongFocus );
setFlag( QQuickItem::ItemAcceptsInputMethod );
/*
QQuickTextInput is a beast of almost 5k lines of code, we don't
want to reimplement that - at least not now.
@ -302,355 +210,11 @@ QskTextInput::~QskTextInput()
{
}
bool QskTextInput::event( QEvent* event )
{
if ( event->type() == QEvent::ShortcutOverride )
{
return m_data->wrappedInput->handleEvent( event );
}
else if ( event->type() == QEvent::LocaleChange )
{
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
}
return Inherited::event( event );
}
void QskTextInput::keyPressEvent( QKeyEvent* event )
{
if ( isEditing() )
{
switch ( event->key() )
{
case Qt::Key_Enter:
case Qt::Key_Return:
{
const auto hints = inputMethodQuery( Qt::ImHints ).toInt();
if ( !( hints & Qt::ImhMultiLine ) )
{
if ( hasAcceptableInput() || fixup() )
{
QGuiApplication::inputMethod()->commit();
setEditing( false );
}
}
break;
}
#if 1
case Qt::Key_Escape:
{
setEditing( false );
break;
}
#endif
}
if ( isEditing() )
{
m_data->wrappedInput->handleEvent( event );
}
else
{
// When returning from a virtual keyboard
qskForceActiveFocus( this, Qt::PopupFocusReason );
}
return;
}
if ( ( m_data->activationModes & ActivationOnKey ) && !event->isAutoRepeat() )
{
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
{
setEditing( true );
return;
}
}
Inherited::keyPressEvent( event );
}
void QskTextInput::keyReleaseEvent( QKeyEvent* event )
{
Inherited::keyReleaseEvent( event );
}
void QskTextInput::mousePressEvent( QMouseEvent* event )
{
m_data->wrappedInput->handleEvent( event );
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskTextInput::mouseMoveEvent( QMouseEvent* event )
{
m_data->wrappedInput->handleEvent( event );
}
void QskTextInput::mouseReleaseEvent( QMouseEvent* event )
{
m_data->wrappedInput->handleEvent( event );
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
setEditing( true );
}
void QskTextInput::mouseDoubleClickEvent( QMouseEvent* event )
{
m_data->wrappedInput->handleEvent( event );
}
void QskTextInput::inputMethodEvent( QInputMethodEvent* event )
{
m_data->wrappedInput->handleEvent( event );
}
void QskTextInput::focusInEvent( QFocusEvent* event )
{
if ( m_data->activationModes & ActivationOnFocus )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
break;
default:
#if 1
// auto selecting the complete text ???
#endif
setEditing( true );
}
}
Inherited::focusInEvent( event );
}
void QskTextInput::focusOutEvent( QFocusEvent* event )
{
switch ( event->reason() )
{
case Qt::ActiveWindowFocusReason:
case Qt::PopupFocusReason:
{
break;
}
default:
{
m_data->wrappedInput->deselect();
setEditing( false );
}
}
Inherited::focusOutEvent( event );
}
void QskTextInput::updateLayout()
{
m_data->wrappedInput->updateMetrics();
qskSetItemGeometry( m_data->wrappedInput, subControlRect( Text ) );
}
void QskTextInput::updateNode( QSGNode* node )
{
m_data->wrappedInput->updateColors();
Inherited::updateNode( node );
}
QString QskTextInput::text() const
{
return m_data->wrappedInput->text();
}
void QskTextInput::setText( const QString& text )
{
m_data->wrappedInput->setText( text );
}
void QskTextInput::clear()
{
m_data->wrappedInput->clear();
}
void QskTextInput::selectAll()
{
m_data->wrappedInput->selectAll();
}
QskTextInput::ActivationModes QskTextInput::activationModes() const
{
return static_cast< QskTextInput::ActivationModes >( m_data->activationModes );
}
void QskTextInput::setActivationModes( ActivationModes modes )
{
if ( static_cast< ActivationModes >( m_data->activationModes ) != modes )
{
m_data->activationModes = modes;
Q_EMIT activationModesChanged();
}
}
static inline void qskUpdateInputMethodFont( const QskTextInput* input )
{
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
qskUpdateInputMethod( input, queries );
}
void QskTextInput::setFontRole( const QskFontRole& role )
{
if ( setFontRoleHint( Text, role ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
void QskTextInput::resetFontRole()
{
if ( resetFontRoleHint( Text ) )
{
qskUpdateInputMethodFont( this );
Q_EMIT fontRoleChanged();
}
}
QskFontRole QskTextInput::fontRole() const
{
return fontRoleHint( Text );
}
void QskTextInput::setAlignment( Qt::Alignment alignment )
{
if ( setAlignmentHint( Text, alignment ) )
{
m_data->wrappedInput->setAlignment( alignment );
Q_EMIT alignmentChanged();
}
}
void QskTextInput::resetAlignment()
{
if ( resetAlignmentHint( Text ) )
{
m_data->wrappedInput->setAlignment( alignment() );
Q_EMIT alignmentChanged();
}
}
Qt::Alignment QskTextInput::alignment() const
{
return alignmentHint( Text, Qt::AlignLeft | Qt::AlignTop );
}
void QskTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
{
m_data->wrappedInput->setWrapMode(
static_cast< QQuickTextInput::WrapMode >( wrapMode ) );
}
QskTextOptions::WrapMode QskTextInput::wrapMode() const
{
return static_cast< QskTextOptions::WrapMode >(
m_data->wrappedInput->wrapMode() );
}
void QskTextInput::setSelectByMouse( bool on )
{
m_data->wrappedInput->setSelectByMouse( on );
}
bool QskTextInput::selectByMouse() const
{
return m_data->wrappedInput->selectByMouse();
}
QFont QskTextInput::font() const
{
return effectiveFont( QskTextInput::Text );
}
bool QskTextInput::isReadOnly() const
{
return m_data->wrappedInput->isReadOnly();
}
void QskTextInput::setReadOnly( bool on )
{
auto input = m_data->wrappedInput;
if ( input->isReadOnly() == on )
return;
#if 1
// do we want to be able to restore the previous policy ?
setFocusPolicy( Qt::NoFocus );
#endif
input->setReadOnly( on );
// we are killing user settings here ?
input->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
qskUpdateInputMethod( this, Qt::ImEnabled );
#if 0
qskUpdateInputMethod( this, Qt::ImReadOnly ); // since 6.2
#endif
setSkinStateFlag( ReadOnly, on );
}
void QskTextInput::setEditing( bool on )
{
if ( isReadOnly() || on == isEditing() )
return;
setSkinStateFlag( Editing, on );
m_data->wrappedInput->setEditing( on );
if ( on )
{
#if 0
updateInputMethod( Qt::ImCursorRectangle | Qt::ImAnchorRectangle );
QGuiApplication::inputMethod()->inputDirection
#endif
qskInputMethodSetVisible( this, true );
}
else
{
if ( hasAcceptableInput() || fixup() )
Q_EMIT m_data->wrappedInput->editingFinished();
#if 0
inputMethod->reset();
#endif
qskInputMethodSetVisible( this, false );
}
Q_EMIT editingChanged( on );
}
bool QskTextInput::isEditing() const
{
return hasSkinState( Editing );
}
void QskTextInput::ensureVisible( int position )
{
m_data->wrappedInput->ensureVisible( position );
}
int QskTextInput::cursorPosition() const
{
return m_data->wrappedInput->cursorPosition();
}
void QskTextInput::setCursorPosition( int pos )
{
m_data->wrappedInput->setCursorPosition( pos );
}
int QskTextInput::maxLength() const
{
return m_data->wrappedInput->maxLength();
@ -734,22 +298,6 @@ QString QskTextInput::displayText() const
return m_data->wrappedInput->displayText();
}
QString QskTextInput::preeditText() const
{
const auto d = QQuickTextInputPrivate::get( m_data->wrappedInput );
return d->m_textLayout.preeditAreaText();
}
bool QskTextInput::overwriteMode() const
{
return m_data->wrappedInput->overwriteMode();
}
void QskTextInput::setOverwriteMode( bool overwrite )
{
m_data->wrappedInput->setOverwriteMode( overwrite );
}
bool QskTextInput::hasAcceptableInput() const
{
return m_data->wrappedInput->hasAcceptableInput();
@ -760,58 +308,9 @@ bool QskTextInput::fixup()
return m_data->wrappedInput->fixup();
}
QVariant QskTextInput::inputMethodQuery(
Qt::InputMethodQuery property ) const
bool QskTextInput::acceptInput()
{
return inputMethodQuery( property, QVariant() );
}
QVariant QskTextInput::inputMethodQuery(
Qt::InputMethodQuery query, const QVariant& argument ) const
{
switch ( query )
{
case Qt::ImEnabled:
{
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
}
case Qt::ImFont:
{
return font();
}
case Qt::ImPreferredLanguage:
{
return locale();
}
case Qt::ImInputItemClipRectangle:
case Qt::ImCursorRectangle:
{
QVariant v = m_data->wrappedInput->inputMethodQuery( query, argument );
#if 1
if ( v.canConvert< QRectF >() )
v.setValue( v.toRectF().translated( m_data->wrappedInput->position() ) );
#endif
return v;
}
default:
{
return m_data->wrappedInput->inputMethodQuery( query, argument );
}
}
}
Qt::InputMethodHints QskTextInput::inputMethodHints() const
{
return m_data->wrappedInput->inputMethodHints();
}
void QskTextInput::setInputMethodHints( Qt::InputMethodHints hints )
{
if ( m_data->wrappedInput->inputMethodHints() != hints )
{
m_data->wrappedInput->setInputMethodHints( hints );
qskUpdateInputMethod( this, Qt::ImHints );
}
return hasAcceptableInput() || fixup();
}
void QskTextInput::setupFrom( const QQuickItem* item )
@ -915,4 +414,10 @@ void QskTextInput::setupFrom( const QQuickItem* item )
setEchoMode( echoMode );
}
QQuickItem* QskTextInput::wrappedInput()
{
return m_data->wrappedInput;
}
#include "QskTextInput.moc"
#include "moc_QskTextInput.cpp"

View File

@ -6,36 +6,15 @@
#ifndef QSK_TEXT_INPUT_H
#define QSK_TEXT_INPUT_H
#include "QskControl.h"
#include "QskAbstractTextInput.h"
#include "QskTextOptions.h"
class QValidator;
class QskFontRole;
class QSK_EXPORT QskTextInput : public QskControl
class QSK_EXPORT QskTextInput : public QskAbstractTextInput
{
Q_OBJECT
Q_PROPERTY( QString text READ text
WRITE setText NOTIFY textChanged USER true )
Q_PROPERTY( QskFontRole fontRole READ fontRole
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
Q_PROPERTY( QFont font READ font )
Q_PROPERTY( Qt::Alignment alignment READ alignment
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
WRITE setWrapMode NOTIFY wrapModeChanged )
Q_PROPERTY( ActivationModes activationModes READ activationModes
WRITE setActivationModes NOTIFY activationModesChanged )
Q_PROPERTY( bool editing READ isEditing
WRITE setEditing NOTIFY editingChanged )
Q_PROPERTY( EchoMode echoMode READ echoMode
WRITE setEchoMode NOTIFY echoModeChanged )
@ -47,30 +26,12 @@ class QSK_EXPORT QskTextInput : public QskControl
WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay
NOTIFY passwordMaskDelayChanged )
Q_PROPERTY( bool selectByMouse READ selectByMouse
WRITE setSelectByMouse )
using Inherited = QskControl;
using Inherited = QskAbstractTextInput;
public:
QSK_SUBCONTROLS( TextPanel, Text )
QSK_SUBCONTROLS( TextPanel )
QSK_STATES( ReadOnly, Editing, Error )
enum ActivationMode : quint8
{
NoActivation,
ActivationOnFocus = 1 << 0,
ActivationOnMouse = 1 << 1,
ActivationOnKey = 1 << 2,
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
};
Q_ENUM( ActivationMode )
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
QSK_STATES( Error )
enum EchoMode : quint8
{
@ -82,39 +43,11 @@ class QSK_EXPORT QskTextInput : public QskControl
Q_ENUM( EchoMode )
QskTextInput( QQuickItem* parent = nullptr );
~QskTextInput() override;
void setupFrom( const QQuickItem* );
QString text() const;
void setFontRole( const QskFontRole& role );
void resetFontRole();
QskFontRole fontRole() const;
void setAlignment( Qt::Alignment );
void resetAlignment();
Qt::Alignment alignment() const;
void setWrapMode( QskTextOptions::WrapMode );
QskTextOptions::WrapMode wrapMode() const;
void setActivationModes( ActivationModes );
ActivationModes activationModes() const;
void setSelectByMouse( bool );
bool selectByMouse() const;
bool isEditing() const;
QFont font() const;
bool isReadOnly() const;
void setReadOnly( bool );
int cursorPosition() const;
void setCursorPosition( int );
int maxLength() const;
void setMaxLength( int );
@ -136,44 +69,14 @@ class QSK_EXPORT QskTextInput : public QskControl
void resetPasswordMaskDelay();
QString displayText() const;
QString preeditText() const;
bool overwriteMode() const;
void setOverwriteMode( bool );
bool hasAcceptableInput() const;
bool fixup();
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& argument ) const;
Qt::InputMethodHints inputMethodHints() const;
void setInputMethodHints( Qt::InputMethodHints );
bool acceptInput() override;
void ensureVisible( int position );
public Q_SLOTS:
void clear();
void selectAll();
void setText( const QString& );
void setEditing( bool );
Q_SIGNALS:
void editingChanged( bool );
void activationModesChanged();
void readOnlyChanged( bool );
void textChanged( const QString& );
void displayTextChanged( const QString& );
void textEdited( const QString& );
void fontRoleChanged();
void alignmentChanged();
void wrapModeChanged( QskTextOptions::WrapMode );
void overwriteModeChanged( bool );
void maximumLengthChanged( int );
void echoModeChanged( EchoMode );
@ -184,32 +87,11 @@ class QSK_EXPORT QskTextInput : public QskControl
void inputMaskChanged( const QString& );
protected:
QskTextInput( QQuickItem* parent = nullptr );
bool event( QEvent* ) override;
void inputMethodEvent( QInputMethodEvent* ) override;
void focusInEvent( QFocusEvent* ) override;
void focusOutEvent( QFocusEvent* ) override;
void mousePressEvent( QMouseEvent* ) override;
void mouseMoveEvent( QMouseEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override;
void mouseDoubleClickEvent( QMouseEvent* ) override;
void keyPressEvent( QKeyEvent* ) override;
void keyReleaseEvent( QKeyEvent* ) override;
void updateLayout() override;
void updateNode( QSGNode* ) override;
QQuickItem* wrappedInput() override final;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextInput::ActivationModes )
Q_DECLARE_METATYPE( QskTextInput::ActivationModes )
#endif

View File

@ -10,8 +10,6 @@
using Q = QskTextInput;
QSK_SYSTEM_STATE( QskTextInputSkinlet, Selected, QskAspect::FirstSystemState << 3 )
QskTextInputSkinlet::QskTextInputSkinlet( QskSkin* skin )
: Inherited( skin )
{

View File

@ -13,8 +13,6 @@ class QSK_EXPORT QskTextInputSkinlet : public QskSkinlet
using Inherited = QskSkinlet;
public:
QSK_STATES( Selected )
enum NodeRole : quint8
{
TextPanelRole,