QskTextField/QskTextInput seperated
This commit is contained in:
parent
74d14b6005
commit
a91dcd5a56
|
|
@ -1776,14 +1776,14 @@ void Editor::setupTextFieldMetrics()
|
||||||
{
|
{
|
||||||
using Q = QskTextField;
|
using Q = QskTextField;
|
||||||
|
|
||||||
setStrutSize( Q::Panel, { -1, 30_px } );
|
setStrutSize( Q::TextPanel, { -1, 30_px } );
|
||||||
setPadding( Q::Panel, { 11_px, 0, 11_px, 0 } );
|
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
||||||
|
|
||||||
setBoxBorderMetrics( Q::Panel, 1_px );
|
setBoxBorderMetrics( Q::TextPanel, 1_px );
|
||||||
for( const auto& state : { Q::Focused, Q::Editing } )
|
for( const auto& state : { Q::Focused, Q::Editing } )
|
||||||
setBoxBorderMetrics( Q::Panel | state, { 1_px, 1_px, 1_px, 2_px } );
|
setBoxBorderMetrics( Q::TextPanel | state, { 1_px, 1_px, 1_px, 2_px } );
|
||||||
|
|
||||||
setBoxShape( Q::Panel, 3_px );
|
setBoxShape( Q::TextPanel, 3_px );
|
||||||
|
|
||||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
setFontRole( Q::Text, Fluent2::Body );
|
setFontRole( Q::Text, Fluent2::Body );
|
||||||
|
|
@ -1801,7 +1801,7 @@ void Editor::setupTextFieldColors(
|
||||||
|
|
||||||
const auto& pal = theme.palette;
|
const auto& pal = theme.palette;
|
||||||
|
|
||||||
setColor( Q::Panel | SK::Selected, pal.fillColor.accent.selectedTextBackground );
|
setColor( Q::TextPanel | SK::Selected, pal.fillColor.accent.selectedTextBackground );
|
||||||
setColor( Q::Text | SK::Selected, pal.fillColor.textOnAccent.selectedText );
|
setColor( Q::Text | SK::Selected, pal.fillColor.textOnAccent.selectedText );
|
||||||
setColor( Q::PlaceholderText, pal.fillColor.text.secondary );
|
setColor( Q::PlaceholderText, pal.fillColor.text.secondary );
|
||||||
|
|
||||||
|
|
@ -1837,7 +1837,7 @@ void Editor::setupTextFieldColors(
|
||||||
textColor = pal.fillColor.text.disabled;
|
textColor = pal.fillColor.text.disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto panel = Q::Panel | section | state;
|
const auto panel = Q::TextPanel | section | state;
|
||||||
const auto text = Q::Text | section | state;
|
const auto text = Q::Text | section | state;
|
||||||
|
|
||||||
panelColor = rgbSolid( panelColor, pal.background.solid.base );
|
panelColor = rgbSolid( panelColor, pal.background.solid.base );
|
||||||
|
|
|
||||||
|
|
@ -397,25 +397,25 @@ void Editor::setupTextField()
|
||||||
{
|
{
|
||||||
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
|
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
|
||||||
|
|
||||||
setColor( Q::Panel | state, m_pal.color( colorGroup, P::Base ) );
|
setColor( Q::TextPanel | state, m_pal.color( colorGroup, P::Base ) );
|
||||||
setColor( Q::Panel | SK::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
|
setColor( Q::TextPanel | SK::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
|
||||||
|
|
||||||
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
|
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
|
||||||
setColor( Q::Text | SK::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
|
setColor( Q::Text | SK::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
|
||||||
setColor( Q::PlaceholderText, m_pal.color( colorGroup, P::PlaceholderText ) );
|
setColor( Q::PlaceholderText, m_pal.color( colorGroup, P::PlaceholderText ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
setColor( Q::Panel | Q::ReadOnly, m_pal.disabled( P::Base ) );
|
setColor( Q::TextPanel | Q::ReadOnly, m_pal.disabled( P::Base ) );
|
||||||
|
|
||||||
setBoxBorderMetrics( Q::Panel, 1_px );
|
setBoxBorderMetrics( Q::TextPanel, 1_px );
|
||||||
|
|
||||||
setBoxBorderColors( Q::Panel, m_pal.outline );
|
setBoxBorderColors( Q::TextPanel, m_pal.outline );
|
||||||
#ifdef SHOW_FOCUS
|
#ifdef SHOW_FOCUS
|
||||||
setBoxBorderColors( Q::Panel | Q::Focused, m_pal.highlightedOutline );
|
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.highlightedOutline );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setBoxShape( Q::Panel, 2_px );
|
setBoxShape( Q::TextPanel, 2_px );
|
||||||
setPadding( Q::Panel, 4_px );
|
setPadding( Q::TextPanel, 4_px );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupProgressBar()
|
void Editor::setupProgressBar()
|
||||||
|
|
|
||||||
|
|
@ -434,12 +434,12 @@ void Editor::setupTextLabel()
|
||||||
void Editor::setupTextField()
|
void Editor::setupTextField()
|
||||||
{
|
{
|
||||||
using Q = QskTextField;
|
using Q = QskTextField;
|
||||||
using SK = QskTextFieldSkinlet;
|
using SK = QskTextInputSkinlet;
|
||||||
|
|
||||||
setStrutSize( Q::Panel, -1.0, 56_px );
|
setStrutSize( Q::Panel, -1.0, 56_px );
|
||||||
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
|
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
|
||||||
setGradient( Q::Panel, m_pal.surfaceVariant );
|
setGradient( Q::Panel, m_pal.surfaceVariant );
|
||||||
setColor( Q::Panel | SK::Selected, m_pal.primary12 );
|
setColor( Q::TextPanel | SK::Selected, m_pal.primary12 );
|
||||||
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
|
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
|
||||||
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
|
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
|
||||||
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
|
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,8 @@ list(APPEND HEADERS
|
||||||
controls/QskTabViewSkinlet.h
|
controls/QskTabViewSkinlet.h
|
||||||
controls/QskTextField.h
|
controls/QskTextField.h
|
||||||
controls/QskTextFieldSkinlet.h
|
controls/QskTextFieldSkinlet.h
|
||||||
|
controls/QskTextInput.h
|
||||||
|
controls/QskTextInputSkinlet.h
|
||||||
controls/QskTextLabel.h
|
controls/QskTextLabel.h
|
||||||
controls/QskTextLabelSkinlet.h
|
controls/QskTextLabelSkinlet.h
|
||||||
controls/QskVariantAnimator.h
|
controls/QskVariantAnimator.h
|
||||||
|
|
@ -387,6 +389,8 @@ list(APPEND SOURCES
|
||||||
controls/QskTabViewSkinlet.cpp
|
controls/QskTabViewSkinlet.cpp
|
||||||
controls/QskTextField.cpp
|
controls/QskTextField.cpp
|
||||||
controls/QskTextFieldSkinlet.cpp
|
controls/QskTextFieldSkinlet.cpp
|
||||||
|
controls/QskTextInput.cpp
|
||||||
|
controls/QskTextInputSkinlet.cpp
|
||||||
controls/QskTextLabel.cpp
|
controls/QskTextLabel.cpp
|
||||||
controls/QskTextLabelSkinlet.cpp
|
controls/QskTextLabelSkinlet.cpp
|
||||||
controls/QskVariantAnimator.cpp
|
controls/QskVariantAnimator.cpp
|
||||||
|
|
|
||||||
|
|
@ -4,514 +4,32 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskTextField.h"
|
#include "QskTextField.h"
|
||||||
#include "QskTextFieldSkinlet.h"
|
|
||||||
#include "QskFontRole.h"
|
|
||||||
#include "QskQuick.h"
|
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
|
||||||
#include <private/qquicktextinput_p.h>
|
|
||||||
#include <private/qquicktextinput_p_p.h>
|
|
||||||
QSK_QT_PRIVATE_END
|
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskTextField, Panel )
|
QSK_SUBCONTROL( QskTextField, Panel )
|
||||||
QSK_SUBCONTROL( QskTextField, Text )
|
|
||||||
QSK_SUBCONTROL( QskTextField, PlaceholderText )
|
QSK_SUBCONTROL( QskTextField, PlaceholderText )
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskTextField, ReadOnly, QskAspect::FirstSystemState << 1 )
|
|
||||||
QSK_SYSTEM_STATE( QskTextField, Editing, QskAspect::FirstSystemState << 2 )
|
|
||||||
|
|
||||||
static inline void qskPropagateReadOnly( QskTextField* input )
|
|
||||||
{
|
|
||||||
Q_EMIT input->readOnlyChanged( input->isReadOnly() );
|
|
||||||
|
|
||||||
QEvent event( QEvent::ReadOnlyChange );
|
|
||||||
QCoreApplication::sendEvent( input, &event );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void qskBindSignals(
|
|
||||||
const QQuickTextInput* input, QskTextField* field )
|
|
||||||
{
|
|
||||||
QObject::connect( input, &QQuickTextInput::textChanged,
|
|
||||||
field, [ field ] { Q_EMIT field->textChanged( field->text() ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::displayTextChanged,
|
|
||||||
field, [ field ] { Q_EMIT field->displayTextChanged( field->displayText() ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::textEdited,
|
|
||||||
field, [ field ] { Q_EMIT field->textEdited( field->text() ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::validatorChanged,
|
|
||||||
field, &QskTextField::validatorChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::inputMaskChanged,
|
|
||||||
field, &QskTextField::inputMaskChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::readOnlyChanged,
|
|
||||||
field, [ field ] { qskPropagateReadOnly( field ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::overwriteModeChanged,
|
|
||||||
field, &QskTextField::overwriteModeChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::maximumLengthChanged,
|
|
||||||
field, &QskTextField::maximumLengthChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::wrapModeChanged,
|
|
||||||
field, [ field ] { Q_EMIT field->wrapModeChanged( field->wrapMode() ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::echoModeChanged,
|
|
||||||
field, [ field ] { Q_EMIT field->echoModeChanged( field->echoMode() ); } );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::passwordCharacterChanged,
|
|
||||||
field, &QskTextField::passwordCharacterChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickTextInput::passwordMaskDelayChanged,
|
|
||||||
field, &QskTextField::passwordMaskDelayChanged );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickItem::implicitWidthChanged,
|
|
||||||
field, &QskControl::resetImplicitSize );
|
|
||||||
|
|
||||||
QObject::connect( input, &QQuickItem::implicitHeightChanged,
|
|
||||||
field, &QskControl::resetImplicitSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class TextInput final : public QQuickTextInput
|
|
||||||
{
|
|
||||||
using Inherited = QQuickTextInput;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TextInput( QskTextField* );
|
|
||||||
|
|
||||||
void setEditing( bool on );
|
|
||||||
|
|
||||||
inline void setAlignment( Qt::Alignment alignment )
|
|
||||||
{
|
|
||||||
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
|
|
||||||
setVAlign( ( VAlignment ) ( int( alignment ) & 0xf0 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fixup()
|
|
||||||
{
|
|
||||||
return QQuickTextInputPrivate::get( this )->fixup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasAcceptableInput() const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
we would like to call QQuickTextInputPrivate::hasAcceptableInput
|
|
||||||
but unfortunately it is private, so we need to hack somthing
|
|
||||||
together
|
|
||||||
*/
|
|
||||||
|
|
||||||
auto that = const_cast< TextInput* >( this );
|
|
||||||
auto d = QQuickTextInputPrivate::get( that );
|
|
||||||
|
|
||||||
if ( d->m_validator )
|
|
||||||
{
|
|
||||||
QString text = displayText();
|
|
||||||
int pos = d->m_cursor;
|
|
||||||
|
|
||||||
const auto state = d->m_validator->validate( text, pos );
|
|
||||||
if ( state != QValidator::Acceptable )
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( d->m_maskData )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We only want to do the check for the maskData here
|
|
||||||
and have to disable d->m_validator temporarily
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Validator final : public QValidator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
State validate( QString&, int& ) const override
|
|
||||||
{
|
|
||||||
return QValidator::Acceptable;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto validator = d->m_validator;
|
|
||||||
|
|
||||||
const auto validInput = d->m_validInput;
|
|
||||||
const auto acceptableInput = d->m_acceptableInput;
|
|
||||||
|
|
||||||
d->m_acceptableInput = true;
|
|
||||||
|
|
||||||
static Validator noValidator;
|
|
||||||
that->setValidator( &noValidator ); // implicitly checking maskData
|
|
||||||
that->setValidator( d->m_validator );
|
|
||||||
|
|
||||||
const bool isAcceptable = d->m_acceptableInput;
|
|
||||||
|
|
||||||
// restoring old values
|
|
||||||
d->m_validInput = validInput;
|
|
||||||
d->m_acceptableInput = acceptableInput;
|
|
||||||
|
|
||||||
return isAcceptable;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateColors();
|
|
||||||
void updateMetrics();
|
|
||||||
|
|
||||||
inline bool handleEvent( QEvent* event )
|
|
||||||
{
|
|
||||||
return this->event( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
|
||||||
void geometryChange(
|
|
||||||
const QRectF& newGeometry, const QRectF& oldGeometry ) override
|
|
||||||
{
|
|
||||||
Inherited::geometryChange( newGeometry, oldGeometry );
|
|
||||||
updateClip();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void geometryChanged(
|
|
||||||
const QRectF& newGeometry, const QRectF& oldGeometry ) override
|
|
||||||
{
|
|
||||||
Inherited::geometryChanged( newGeometry, oldGeometry );
|
|
||||||
updateClip();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void updateClip()
|
|
||||||
{
|
|
||||||
setClip( ( contentWidth() > width() ) ||
|
|
||||||
( contentHeight() > height() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
QSGNode* updatePaintNode(
|
|
||||||
QSGNode* oldNode, UpdatePaintNodeData* data ) override
|
|
||||||
{
|
|
||||||
updateColors();
|
|
||||||
return Inherited::updatePaintNode( oldNode, data );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TextInput::TextInput( QskTextField* textField )
|
|
||||||
: QQuickTextInput( textField )
|
|
||||||
{
|
|
||||||
classBegin();
|
|
||||||
|
|
||||||
setActiveFocusOnTab( false );
|
|
||||||
setFlag( ItemAcceptsInputMethod, false );
|
|
||||||
setFocusOnPress( false );
|
|
||||||
|
|
||||||
componentComplete();
|
|
||||||
|
|
||||||
connect( this, &TextInput::contentSizeChanged,
|
|
||||||
this, &TextInput::updateClip );
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextInput::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 TextInput::updateMetrics()
|
|
||||||
{
|
|
||||||
auto textField = static_cast< const QskTextField* >( parentItem() );
|
|
||||||
|
|
||||||
setAlignment( textField->alignment() );
|
|
||||||
setFont( textField->font() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextInput::updateColors()
|
|
||||||
{
|
|
||||||
auto textField = static_cast< const QskTextField* >( parentItem() );
|
|
||||||
auto d = QQuickTextInputPrivate::get( this );
|
|
||||||
|
|
||||||
bool isDirty = false;
|
|
||||||
|
|
||||||
QColor color;
|
|
||||||
|
|
||||||
color = textField->color( QskTextField::Text );
|
|
||||||
if ( d->color != color )
|
|
||||||
{
|
|
||||||
d->color = color;
|
|
||||||
isDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( d->hasSelectedText() )
|
|
||||||
{
|
|
||||||
color = textField->color( QskTextField::Panel | QskTextFieldSkinlet::Selected );
|
|
||||||
if ( d->selectionColor != color )
|
|
||||||
{
|
|
||||||
d->selectionColor = color;
|
|
||||||
isDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
color = textField->color( QskTextField::Text | QskTextFieldSkinlet::Selected );
|
|
||||||
if ( d->selectedTextColor != color )
|
|
||||||
{
|
|
||||||
d->selectedTextColor = color;
|
|
||||||
isDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isDirty )
|
|
||||||
{
|
|
||||||
d->textLayoutDirty = true;
|
|
||||||
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class QskTextField::PrivateData
|
class QskTextField::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextInput* textInput;
|
|
||||||
QString placeholderText;
|
QString placeholderText;
|
||||||
|
|
||||||
unsigned int activationModes : 3;
|
|
||||||
bool hasPanel : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskTextField::QskTextField( QQuickItem* parent )
|
QskTextField::QskTextField( QQuickItem* parent )
|
||||||
: Inherited( parent )
|
: Inherited( parent )
|
||||||
, m_data( new PrivateData() )
|
, m_data( new PrivateData() )
|
||||||
{
|
{
|
||||||
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
|
|
||||||
m_data->hasPanel = true;
|
|
||||||
|
|
||||||
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.
|
|
||||||
So this is more or less a simple wrapper making everything
|
|
||||||
conforming to qskinny.
|
|
||||||
*/
|
|
||||||
|
|
||||||
m_data->textInput = new TextInput( this );
|
|
||||||
qskBindSignals( m_data->textInput, this );
|
|
||||||
|
|
||||||
setAcceptedMouseButtons( m_data->textInput->acceptedMouseButtons() );
|
|
||||||
m_data->textInput->setAcceptedMouseButtons( Qt::NoButton );
|
|
||||||
|
|
||||||
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskTextField::QskTextField( const QString& text, QQuickItem* parent )
|
QskTextField::QskTextField( const QString& text, QQuickItem* parent )
|
||||||
: QskTextField( parent )
|
: QskTextField( parent )
|
||||||
{
|
{
|
||||||
m_data->textInput->setText( text );
|
setText( text );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskTextField::~QskTextField()
|
QskTextField::~QskTextField()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskTextField::setPanel( bool on )
|
|
||||||
{
|
|
||||||
if ( on != m_data->hasPanel )
|
|
||||||
{
|
|
||||||
m_data->hasPanel = on;
|
|
||||||
|
|
||||||
resetImplicitSize();
|
|
||||||
polish();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::hasPanel() const
|
|
||||||
{
|
|
||||||
return m_data->hasPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::event( QEvent* event )
|
|
||||||
{
|
|
||||||
if ( event->type() == QEvent::ShortcutOverride )
|
|
||||||
{
|
|
||||||
return m_data->textInput->handleEvent( event );
|
|
||||||
}
|
|
||||||
else if ( event->type() == QEvent::LocaleChange )
|
|
||||||
{
|
|
||||||
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::event( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::keyPressEvent( QKeyEvent* event )
|
|
||||||
{
|
|
||||||
if ( isEditing() )
|
|
||||||
{
|
|
||||||
switch ( event->key() )
|
|
||||||
{
|
|
||||||
case Qt::Key_Enter:
|
|
||||||
case Qt::Key_Return:
|
|
||||||
{
|
|
||||||
if ( hasAcceptableInput() || fixup() )
|
|
||||||
{
|
|
||||||
QGuiApplication::inputMethod()->commit();
|
|
||||||
|
|
||||||
if ( !( inputMethodHints() & Qt::ImhMultiLine ) )
|
|
||||||
{
|
|
||||||
setEditing( false );
|
|
||||||
|
|
||||||
// When returning from a virtual keyboard
|
|
||||||
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
case Qt::Key_Escape:
|
|
||||||
{
|
|
||||||
setEditing( false );
|
|
||||||
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_data->textInput->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 QskTextField::keyReleaseEvent( QKeyEvent* event )
|
|
||||||
{
|
|
||||||
Inherited::keyReleaseEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::mousePressEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
m_data->textInput->handleEvent( event );
|
|
||||||
|
|
||||||
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
|
||||||
setEditing( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::mouseMoveEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
m_data->textInput->handleEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::mouseReleaseEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
m_data->textInput->handleEvent( event );
|
|
||||||
|
|
||||||
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
|
||||||
setEditing( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::mouseDoubleClickEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
m_data->textInput->handleEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::inputMethodEvent( QInputMethodEvent* event )
|
|
||||||
{
|
|
||||||
m_data->textInput->handleEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::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 QskTextField::focusOutEvent( QFocusEvent* event )
|
|
||||||
{
|
|
||||||
switch ( event->reason() )
|
|
||||||
{
|
|
||||||
case Qt::ActiveWindowFocusReason:
|
|
||||||
case Qt::PopupFocusReason:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_data->textInput->deselect();
|
|
||||||
setEditing( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Inherited::focusOutEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::updateLayout()
|
|
||||||
{
|
|
||||||
m_data->textInput->updateMetrics();
|
|
||||||
qskSetItemGeometry( m_data->textInput, subControlRect( Text ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::updateNode( QSGNode* node )
|
|
||||||
{
|
|
||||||
m_data->textInput->updateColors();
|
|
||||||
Inherited::updateNode( node );
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QskTextField::text() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setText( const QString& text )
|
|
||||||
{
|
|
||||||
m_data->textInput->setText( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setPlaceholderText( const QString& text )
|
void QskTextField::setPlaceholderText( const QString& text )
|
||||||
{
|
{
|
||||||
if ( m_data->placeholderText != text )
|
if ( m_data->placeholderText != text )
|
||||||
|
|
@ -526,437 +44,4 @@ QString QskTextField::placeholderText() const
|
||||||
return m_data->placeholderText;
|
return m_data->placeholderText;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskTextField::ActivationModes QskTextField::activationModes() const
|
|
||||||
{
|
|
||||||
return static_cast< QskTextField::ActivationModes >( m_data->activationModes );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setActivationModes( ActivationModes modes )
|
|
||||||
{
|
|
||||||
if ( static_cast< ActivationModes >( m_data->activationModes ) != modes )
|
|
||||||
{
|
|
||||||
m_data->activationModes = modes;
|
|
||||||
Q_EMIT activationModesChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void qskUpdateInputMethodFont( const QskTextField* input )
|
|
||||||
{
|
|
||||||
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
|
|
||||||
qskUpdateInputMethod( input, queries );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setFontRole( const QskFontRole& role )
|
|
||||||
{
|
|
||||||
if ( setFontRoleHint( Text, role ) )
|
|
||||||
{
|
|
||||||
qskUpdateInputMethodFont( this );
|
|
||||||
Q_EMIT fontRoleChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::resetFontRole()
|
|
||||||
{
|
|
||||||
if ( resetFontRoleHint( Text ) )
|
|
||||||
{
|
|
||||||
qskUpdateInputMethodFont( this );
|
|
||||||
Q_EMIT fontRoleChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QskFontRole QskTextField::fontRole() const
|
|
||||||
{
|
|
||||||
return fontRoleHint( Text );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setAlignment( Qt::Alignment alignment )
|
|
||||||
{
|
|
||||||
if ( setAlignmentHint( Text, alignment ) )
|
|
||||||
{
|
|
||||||
m_data->textInput->setAlignment( alignment );
|
|
||||||
Q_EMIT alignmentChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::resetAlignment()
|
|
||||||
{
|
|
||||||
if ( resetAlignmentHint( Text ) )
|
|
||||||
{
|
|
||||||
m_data->textInput->setAlignment( alignment() );
|
|
||||||
Q_EMIT alignmentChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::Alignment QskTextField::alignment() const
|
|
||||||
{
|
|
||||||
return alignmentHint( Text, Qt::AlignLeft | Qt::AlignTop );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setWrapMode( QskTextOptions::WrapMode wrapMode )
|
|
||||||
{
|
|
||||||
m_data->textInput->setWrapMode(
|
|
||||||
static_cast< QQuickTextInput::WrapMode >( wrapMode ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskTextOptions::WrapMode QskTextField::wrapMode() const
|
|
||||||
{
|
|
||||||
return static_cast< QskTextOptions::WrapMode >(
|
|
||||||
m_data->textInput->wrapMode() );
|
|
||||||
}
|
|
||||||
|
|
||||||
QFont QskTextField::font() const
|
|
||||||
{
|
|
||||||
return effectiveFont( QskTextField::Text );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::isReadOnly() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->isReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setReadOnly( bool on )
|
|
||||||
{
|
|
||||||
auto input = m_data->textInput;
|
|
||||||
|
|
||||||
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 );
|
|
||||||
|
|
||||||
setSkinStateFlag( ReadOnly, on );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setEditing( bool on )
|
|
||||||
{
|
|
||||||
if ( isReadOnly() || on == isEditing() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
setSkinStateFlag( Editing, on );
|
|
||||||
m_data->textInput->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->textInput->editingFinished();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
inputMethod->reset();
|
|
||||||
#endif
|
|
||||||
qskInputMethodSetVisible( this, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_EMIT editingChanged( on );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::isEditing() const
|
|
||||||
{
|
|
||||||
return hasSkinState( Editing );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::ensureVisible( int position )
|
|
||||||
{
|
|
||||||
m_data->textInput->ensureVisible( position );
|
|
||||||
}
|
|
||||||
|
|
||||||
int QskTextField::cursorPosition() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->cursorPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setCursorPosition( int pos )
|
|
||||||
{
|
|
||||||
m_data->textInput->setCursorPosition( pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
int QskTextField::maxLength() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->maxLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setMaxLength( int length )
|
|
||||||
{
|
|
||||||
m_data->textInput->setMaxLength( length );
|
|
||||||
}
|
|
||||||
|
|
||||||
QValidator* QskTextField::validator() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->validator();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setValidator( QValidator* validator )
|
|
||||||
{
|
|
||||||
m_data->textInput->setValidator( validator );
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QskTextField::inputMask() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->inputMask();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setInputMask( const QString& mask )
|
|
||||||
{
|
|
||||||
m_data->textInput->setInputMask( mask );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskTextField::EchoMode QskTextField::echoMode() const
|
|
||||||
{
|
|
||||||
const auto mode = m_data->textInput->echoMode();
|
|
||||||
return static_cast< QskTextField::EchoMode >( mode );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setEchoMode( EchoMode mode )
|
|
||||||
{
|
|
||||||
if ( mode != echoMode() )
|
|
||||||
{
|
|
||||||
m_data->textInput->setEchoMode(
|
|
||||||
static_cast< QQuickTextInput::EchoMode >( mode ) );
|
|
||||||
|
|
||||||
qskUpdateInputMethod( this, Qt::ImHints );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QskTextField::passwordCharacter() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->passwordCharacter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setPasswordCharacter( const QString& text )
|
|
||||||
{
|
|
||||||
m_data->textInput->setPasswordCharacter( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::resetPasswordCharacter()
|
|
||||||
{
|
|
||||||
m_data->textInput->setPasswordCharacter(
|
|
||||||
QGuiApplication::styleHints()->passwordMaskCharacter() );
|
|
||||||
}
|
|
||||||
|
|
||||||
int QskTextField::passwordMaskDelay() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->passwordMaskDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setPasswordMaskDelay( int ms )
|
|
||||||
{
|
|
||||||
m_data->textInput->setPasswordMaskDelay( ms );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::resetPasswordMaskDelay()
|
|
||||||
{
|
|
||||||
m_data->textInput->resetPasswordMaskDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QskTextField::displayText() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->displayText();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QskTextField::preeditText() const
|
|
||||||
{
|
|
||||||
const auto d = QQuickTextInputPrivate::get( m_data->textInput );
|
|
||||||
return d->m_textLayout.preeditAreaText();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::overwriteMode() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->overwriteMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setOverwriteMode( bool overwrite )
|
|
||||||
{
|
|
||||||
m_data->textInput->setOverwriteMode( overwrite );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::hasAcceptableInput() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->hasAcceptableInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::fixup()
|
|
||||||
{
|
|
||||||
return m_data->textInput->fixup();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant QskTextField::inputMethodQuery(
|
|
||||||
Qt::InputMethodQuery property ) const
|
|
||||||
{
|
|
||||||
return inputMethodQuery( property, QVariant() );
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant QskTextField::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->textInput->inputMethodQuery( query, argument );
|
|
||||||
#if 1
|
|
||||||
if ( v.canConvert< QRectF >() )
|
|
||||||
v.setValue( v.toRectF().translated( m_data->textInput->position() ) );
|
|
||||||
#endif
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return m_data->textInput->inputMethodQuery( query, argument );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::canUndo() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->canUndo();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskTextField::canRedo() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->canRedo();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::InputMethodHints QskTextField::inputMethodHints() const
|
|
||||||
{
|
|
||||||
return m_data->textInput->inputMethodHints();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setInputMethodHints( Qt::InputMethodHints hints )
|
|
||||||
{
|
|
||||||
if ( m_data->textInput->inputMethodHints() != hints )
|
|
||||||
{
|
|
||||||
m_data->textInput->setInputMethodHints( hints );
|
|
||||||
qskUpdateInputMethod( this, Qt::ImHints );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskTextField::setupFrom( const QQuickItem* item )
|
|
||||||
{
|
|
||||||
if ( item == nullptr )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// finding attributes from the input hints of item
|
|
||||||
|
|
||||||
int maxCharacters = 32767;
|
|
||||||
QskTextField::EchoMode echoMode = QskTextField::Normal;
|
|
||||||
|
|
||||||
Qt::InputMethodQueries queries = Qt::ImQueryAll;
|
|
||||||
queries &= ~Qt::ImEnabled;
|
|
||||||
|
|
||||||
QInputMethodQueryEvent event( queries );
|
|
||||||
QCoreApplication::sendEvent( const_cast< QQuickItem* >( item ), &event );
|
|
||||||
|
|
||||||
if ( event.queries() & Qt::ImHints )
|
|
||||||
{
|
|
||||||
const auto hints = static_cast< Qt::InputMethodHints >(
|
|
||||||
event.value( Qt::ImHints ).toInt() );
|
|
||||||
|
|
||||||
if ( hints & Qt::ImhHiddenText )
|
|
||||||
echoMode = QskTextField::NoEcho;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( event.queries() & Qt::ImMaximumTextLength )
|
|
||||||
{
|
|
||||||
// needs to be handled before Qt::ImCursorPosition !
|
|
||||||
|
|
||||||
const auto max = event.value( Qt::ImMaximumTextLength ).toInt();
|
|
||||||
maxCharacters = qBound( 0, max, maxCharacters );
|
|
||||||
}
|
|
||||||
|
|
||||||
setMaxLength( maxCharacters );
|
|
||||||
|
|
||||||
if ( event.queries() & Qt::ImSurroundingText )
|
|
||||||
{
|
|
||||||
const auto text = event.value( Qt::ImSurroundingText ).toString();
|
|
||||||
setText( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( event.queries() & Qt::ImCursorPosition )
|
|
||||||
{
|
|
||||||
const auto pos = event.value( Qt::ImCursorPosition ).toInt();
|
|
||||||
setCursorPosition( pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( event.queries() & Qt::ImCurrentSelection )
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
const auto text = event.value( Qt::ImCurrentSelection ).toString();
|
|
||||||
if ( !text.isEmpty() )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int passwordMaskDelay = -1;
|
|
||||||
QString passwordCharacter;
|
|
||||||
|
|
||||||
if ( echoMode == QskTextField::NoEcho )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Qt::ImhHiddenText does not provide information
|
|
||||||
to decide between NoEcho/Password, or provides
|
|
||||||
more details about how to deal with hidden inputs.
|
|
||||||
So we try to find out more from trying some properties.
|
|
||||||
*/
|
|
||||||
|
|
||||||
QVariant value;
|
|
||||||
|
|
||||||
value = item->property( "passwordMaskDelay" );
|
|
||||||
if ( value.canConvert< int >() )
|
|
||||||
passwordMaskDelay = value.toInt();
|
|
||||||
|
|
||||||
value = item->property( "passwordCharacter" );
|
|
||||||
if ( value.canConvert< QString >() )
|
|
||||||
passwordCharacter = value.toString();
|
|
||||||
|
|
||||||
value = item->property( "echoMode" );
|
|
||||||
if ( value.canConvert< int >() )
|
|
||||||
{
|
|
||||||
const auto mode = value.toInt();
|
|
||||||
if ( mode == QskTextField::Password )
|
|
||||||
echoMode = QskTextField::Password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( passwordMaskDelay >= 0 )
|
|
||||||
setPasswordMaskDelay( passwordMaskDelay );
|
|
||||||
else
|
|
||||||
resetPasswordMaskDelay();
|
|
||||||
|
|
||||||
if ( !passwordCharacter.isEmpty() )
|
|
||||||
setPasswordCharacter( passwordCharacter );
|
|
||||||
else
|
|
||||||
resetPasswordCharacter();
|
|
||||||
|
|
||||||
setEchoMode( echoMode );
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_QskTextField.cpp"
|
#include "moc_QskTextField.cpp"
|
||||||
|
|
|
||||||
|
|
@ -6,218 +6,34 @@
|
||||||
#ifndef QSK_TEXT_FIELD_H
|
#ifndef QSK_TEXT_FIELD_H
|
||||||
#define QSK_TEXT_FIELD_H
|
#define QSK_TEXT_FIELD_H
|
||||||
|
|
||||||
#include "QskControl.h"
|
#include "QskTextInput.h"
|
||||||
#include "QskTextOptions.h"
|
|
||||||
|
|
||||||
class QValidator;
|
class QSK_EXPORT QskTextField : public QskTextInput
|
||||||
class QskFontRole;
|
|
||||||
|
|
||||||
class QSK_EXPORT QskTextField : public QskControl
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged USER true)
|
|
||||||
|
|
||||||
Q_PROPERTY( QString placeholderText READ placeholderText
|
Q_PROPERTY( QString placeholderText READ placeholderText
|
||||||
WRITE setPlaceholderText NOTIFY placeholderTextChanged )
|
WRITE setPlaceholderText NOTIFY placeholderTextChanged )
|
||||||
|
|
||||||
Q_PROPERTY( QskFontRole fontRole READ fontRole
|
using Inherited = QskTextInput;
|
||||||
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 )
|
|
||||||
|
|
||||||
Q_PROPERTY( QString passwordCharacter READ passwordCharacter
|
|
||||||
WRITE setPasswordCharacter RESET resetPasswordCharacter
|
|
||||||
NOTIFY passwordCharacterChanged )
|
|
||||||
|
|
||||||
Q_PROPERTY( int passwordMaskDelay READ passwordMaskDelay
|
|
||||||
WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay
|
|
||||||
NOTIFY passwordMaskDelayChanged )
|
|
||||||
|
|
||||||
Q_PROPERTY( bool panel READ hasPanel
|
|
||||||
WRITE setPanel NOTIFY panelChanged )
|
|
||||||
|
|
||||||
using Inherited = QskControl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Panel, Text, PlaceholderText )
|
QSK_SUBCONTROLS( Panel, PlaceholderText )
|
||||||
QSK_STATES( ReadOnly, Editing )
|
|
||||||
|
|
||||||
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 )
|
|
||||||
|
|
||||||
enum EchoMode : quint8
|
|
||||||
{
|
|
||||||
Normal,
|
|
||||||
NoEcho,
|
|
||||||
Password,
|
|
||||||
PasswordEchoOnEdit
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_ENUM( EchoMode )
|
|
||||||
|
|
||||||
QskTextField( QQuickItem* parent = nullptr );
|
QskTextField( QQuickItem* parent = nullptr );
|
||||||
QskTextField( const QString& text, QQuickItem* parent = nullptr );
|
QskTextField( const QString& text, QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
~QskTextField() override;
|
~QskTextField() override;
|
||||||
|
|
||||||
void setupFrom( const QQuickItem* );
|
|
||||||
|
|
||||||
QString text() const;
|
|
||||||
|
|
||||||
void setPlaceholderText( const QString& );
|
void setPlaceholderText( const QString& );
|
||||||
QString placeholderText() const;
|
QString placeholderText() const;
|
||||||
|
|
||||||
void setPanel( bool );
|
|
||||||
bool hasPanel() 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;
|
|
||||||
|
|
||||||
bool isEditing() const;
|
|
||||||
|
|
||||||
QFont font() const;
|
|
||||||
|
|
||||||
bool isReadOnly() const;
|
|
||||||
void setReadOnly( bool );
|
|
||||||
|
|
||||||
int cursorPosition() const;
|
|
||||||
void setCursorPosition( int );
|
|
||||||
|
|
||||||
int maxLength() const;
|
|
||||||
void setMaxLength( int );
|
|
||||||
|
|
||||||
QValidator* validator() const;
|
|
||||||
void setValidator( QValidator* );
|
|
||||||
|
|
||||||
QString inputMask() const;
|
|
||||||
void setInputMask( const QString& );
|
|
||||||
|
|
||||||
EchoMode echoMode() const;
|
|
||||||
void setEchoMode( EchoMode );
|
|
||||||
|
|
||||||
QString passwordCharacter() const;
|
|
||||||
void setPasswordCharacter( const QString& );
|
|
||||||
void resetPasswordCharacter();
|
|
||||||
|
|
||||||
int passwordMaskDelay() const;
|
|
||||||
void setPasswordMaskDelay( int );
|
|
||||||
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;
|
|
||||||
|
|
||||||
bool canUndo() const;
|
|
||||||
bool canRedo() const;
|
|
||||||
|
|
||||||
Qt::InputMethodHints inputMethodHints() const;
|
|
||||||
void setInputMethodHints( Qt::InputMethodHints );
|
|
||||||
|
|
||||||
void ensureVisible( int position );
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void setText( const QString& );
|
|
||||||
void setEditing( bool );
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void editingChanged( bool );
|
|
||||||
|
|
||||||
void activationModesChanged();
|
|
||||||
void readOnlyChanged( bool );
|
|
||||||
void panelChanged( bool );
|
|
||||||
|
|
||||||
void textChanged( const QString& );
|
|
||||||
void displayTextChanged( const QString& );
|
|
||||||
|
|
||||||
void textEdited( const QString& );
|
|
||||||
void placeholderTextChanged( const QString& );
|
void placeholderTextChanged( const QString& );
|
||||||
|
|
||||||
void fontRoleChanged();
|
|
||||||
void alignmentChanged();
|
|
||||||
void wrapModeChanged( QskTextOptions::WrapMode );
|
|
||||||
|
|
||||||
void overwriteModeChanged( bool );
|
|
||||||
void maximumLengthChanged( int );
|
|
||||||
|
|
||||||
void echoModeChanged( EchoMode );
|
|
||||||
void passwordMaskDelayChanged();
|
|
||||||
void passwordCharacterChanged();
|
|
||||||
|
|
||||||
void validatorChanged();
|
|
||||||
void inputMaskChanged( const QString& );
|
|
||||||
|
|
||||||
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:
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextField::ActivationModes )
|
|
||||||
Q_DECLARE_METATYPE( QskTextField::ActivationModes )
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6,27 +6,12 @@
|
||||||
#include "QskTextFieldSkinlet.h"
|
#include "QskTextFieldSkinlet.h"
|
||||||
#include "QskTextField.h"
|
#include "QskTextField.h"
|
||||||
|
|
||||||
#include <qfontmetrics.h>
|
|
||||||
|
|
||||||
using Q = QskTextField;
|
using Q = QskTextField;
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskTextFieldSkinlet, Selected, QskAspect::FirstSystemState << 3 )
|
|
||||||
|
|
||||||
static QString qskEffectivePlaceholderText( const QskTextField* textField )
|
|
||||||
{
|
|
||||||
if ( textField->text().isEmpty() &&
|
|
||||||
!( textField->isReadOnly() || textField->isEditing() ) )
|
|
||||||
{
|
|
||||||
return textField->placeholderText();
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QskTextFieldSkinlet::QskTextFieldSkinlet( QskSkin* skin )
|
QskTextFieldSkinlet::QskTextFieldSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
setNodeRoles( { PanelRole, PlaceholderTextRole, } );
|
setNodeRoles( { PanelRole, TextPanelRole, PlaceholderTextRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskTextFieldSkinlet::~QskTextFieldSkinlet()
|
QskTextFieldSkinlet::~QskTextFieldSkinlet()
|
||||||
|
|
@ -37,14 +22,12 @@ QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
if ( subControl == Q::Panel )
|
if ( subControl == Q::Panel )
|
||||||
{
|
|
||||||
return contentsRect;
|
return contentsRect;
|
||||||
}
|
|
||||||
else if ( subControl == Q::Text )
|
if ( subControl == Q::TextPanel )
|
||||||
{
|
|
||||||
return skinnable->subControlContentsRect( contentsRect, Q::Panel );
|
return skinnable->subControlContentsRect( contentsRect, Q::Panel );
|
||||||
}
|
|
||||||
else if ( subControl == Q::PlaceholderText )
|
if ( subControl == Q::PlaceholderText )
|
||||||
{
|
{
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
const auto textField = static_cast< const QskTextField* >( skinnable );
|
||||||
if( textField->text().isEmpty() )
|
if( textField->text().isEmpty() )
|
||||||
|
|
@ -65,14 +48,12 @@ QSGNode* QskTextFieldSkinlet::updateSubNode(
|
||||||
{
|
{
|
||||||
case PanelRole:
|
case PanelRole:
|
||||||
{
|
{
|
||||||
if ( !textField->hasPanel() )
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return updateBoxNode( skinnable, node, Q::Panel );
|
return updateBoxNode( skinnable, node, Q::Panel );
|
||||||
}
|
}
|
||||||
|
|
||||||
case PlaceholderTextRole:
|
case PlaceholderTextRole:
|
||||||
{
|
{
|
||||||
const auto text = qskEffectivePlaceholderText( textField );
|
const auto text = effectivePlaceholderText( textField );
|
||||||
if ( text.isEmpty() )
|
if ( text.isEmpty() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
@ -95,24 +76,28 @@ QSGNode* QskTextFieldSkinlet::updateSubNode(
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
Qt::SizeHint which, const QSizeF& ) const
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||||
{
|
{
|
||||||
if ( which != Qt::PreferredSize )
|
if ( which != Qt::PreferredSize )
|
||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
auto hint = Inherited::sizeHint( skinnable, which, constraint );
|
||||||
|
hint = skinnable->outerBoxSize( Q::Panel, hint );
|
||||||
const QFontMetricsF fm( textField->effectiveFont( Q::Text ) );
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Panel ) );
|
||||||
|
|
||||||
auto hint = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, textField->text() );
|
|
||||||
|
|
||||||
if ( textField->hasPanel() )
|
|
||||||
{
|
|
||||||
hint = textField->outerBoxSize( Q::Panel, hint );
|
|
||||||
hint = hint.expandedTo( textField->strutSizeHint( Q::Panel ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QskTextFieldSkinlet::effectivePlaceholderText(
|
||||||
|
const QskTextField* textField ) const
|
||||||
|
{
|
||||||
|
if ( textField->text().isEmpty() &&
|
||||||
|
!( textField->isReadOnly() || textField->isEditing() ) )
|
||||||
|
{
|
||||||
|
return textField->placeholderText();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskTextFieldSkinlet.cpp"
|
#include "moc_QskTextFieldSkinlet.cpp"
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,21 @@
|
||||||
#ifndef QSK_TEXT_FIELD_SKINLET_H
|
#ifndef QSK_TEXT_FIELD_SKINLET_H
|
||||||
#define QSK_TEXT_FIELD_SKINLET_H
|
#define QSK_TEXT_FIELD_SKINLET_H
|
||||||
|
|
||||||
#include "QskSkinlet.h"
|
#include "QskTextInputSkinlet.h"
|
||||||
|
|
||||||
class QSK_EXPORT QskTextFieldSkinlet : public QskSkinlet
|
class QskTextField;
|
||||||
|
|
||||||
|
class QSK_EXPORT QskTextFieldSkinlet : public QskTextInputSkinlet
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
||||||
using Inherited = QskSkinlet;
|
using Inherited = QskTextInputSkinlet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_STATES( Selected )
|
|
||||||
|
|
||||||
enum NodeRole : quint8
|
enum NodeRole : quint8
|
||||||
{
|
{
|
||||||
PanelRole,
|
PanelRole = QskTextInputSkinlet::RoleCount,
|
||||||
|
|
||||||
PlaceholderTextRole,
|
PlaceholderTextRole,
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
|
@ -36,6 +37,8 @@ class QSK_EXPORT QskTextFieldSkinlet : public QskSkinlet
|
||||||
protected:
|
protected:
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
|
virtual QString effectivePlaceholderText( const QskTextField* ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,917 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskTextInput.h"
|
||||||
|
#include "QskTextInputSkinlet.h"
|
||||||
|
#include "QskFontRole.h"
|
||||||
|
#include "QskQuick.h"
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquicktextinput_p.h>
|
||||||
|
#include <private/qquicktextinput_p_p.h>
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
Q_EMIT input->readOnlyChanged( input->isReadOnly() );
|
||||||
|
|
||||||
|
QEvent event( QEvent::ReadOnlyChange );
|
||||||
|
QCoreApplication::sendEvent( input, &event );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void qskBindSignals(
|
||||||
|
const QQuickTextInput* wrappedInput, QskTextInput* input )
|
||||||
|
{
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::textChanged,
|
||||||
|
input, [ input ] { Q_EMIT input->textChanged( input->text() ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::displayTextChanged,
|
||||||
|
input, [ input ] { Q_EMIT input->displayTextChanged( input->displayText() ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::textEdited,
|
||||||
|
input, [ input ] { Q_EMIT input->textEdited( input->text() ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::validatorChanged,
|
||||||
|
input, &QskTextInput::validatorChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::inputMaskChanged,
|
||||||
|
input, &QskTextInput::inputMaskChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::readOnlyChanged,
|
||||||
|
input, [ input ] { qskPropagateReadOnly( input ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::overwriteModeChanged,
|
||||||
|
input, &QskTextInput::overwriteModeChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::maximumLengthChanged,
|
||||||
|
input, &QskTextInput::maximumLengthChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::wrapModeChanged,
|
||||||
|
input, [ input ] { Q_EMIT input->wrapModeChanged( input->wrapMode() ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::echoModeChanged,
|
||||||
|
input, [ input ] { Q_EMIT input->echoModeChanged( input->echoMode() ); } );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::passwordCharacterChanged,
|
||||||
|
input, &QskTextInput::passwordCharacterChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickTextInput::passwordMaskDelayChanged,
|
||||||
|
input, &QskTextInput::passwordMaskDelayChanged );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickItem::implicitWidthChanged,
|
||||||
|
input, &QskControl::resetImplicitSize );
|
||||||
|
|
||||||
|
QObject::connect( wrappedInput, &QQuickItem::implicitHeightChanged,
|
||||||
|
input, &QskControl::resetImplicitSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class QuickTextInput final : public QQuickTextInput
|
||||||
|
{
|
||||||
|
using Inherited = QQuickTextInput;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QuickTextInput( QskTextInput* );
|
||||||
|
|
||||||
|
void setEditing( bool on );
|
||||||
|
|
||||||
|
inline void setAlignment( Qt::Alignment alignment )
|
||||||
|
{
|
||||||
|
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
|
||||||
|
setVAlign( ( VAlignment ) ( int( alignment ) & 0xf0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fixup()
|
||||||
|
{
|
||||||
|
return QQuickTextInputPrivate::get( this )->fixup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAcceptableInput() const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
we would like to call QQuickTextInputPrivate::hasAcceptableInput
|
||||||
|
but unfortunately it is private, so we need to hack somthing
|
||||||
|
together
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto that = const_cast< QuickTextInput* >( this );
|
||||||
|
auto d = QQuickTextInputPrivate::get( that );
|
||||||
|
|
||||||
|
if ( d->m_validator )
|
||||||
|
{
|
||||||
|
QString text = displayText();
|
||||||
|
int pos = d->m_cursor;
|
||||||
|
|
||||||
|
const auto state = d->m_validator->validate( text, pos );
|
||||||
|
if ( state != QValidator::Acceptable )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( d->m_maskData )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We only want to do the check for the maskData here
|
||||||
|
and have to disable d->m_validator temporarily
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Validator final : public QValidator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
State validate( QString&, int& ) const override
|
||||||
|
{
|
||||||
|
return QValidator::Acceptable;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto validator = d->m_validator;
|
||||||
|
|
||||||
|
const auto validInput = d->m_validInput;
|
||||||
|
const auto acceptableInput = d->m_acceptableInput;
|
||||||
|
|
||||||
|
d->m_acceptableInput = true;
|
||||||
|
|
||||||
|
static Validator noValidator;
|
||||||
|
that->setValidator( &noValidator ); // implicitly checking maskData
|
||||||
|
that->setValidator( d->m_validator );
|
||||||
|
|
||||||
|
const bool isAcceptable = d->m_acceptableInput;
|
||||||
|
|
||||||
|
// restoring old values
|
||||||
|
d->m_validInput = validInput;
|
||||||
|
d->m_acceptableInput = acceptableInput;
|
||||||
|
|
||||||
|
return isAcceptable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateColors();
|
||||||
|
void updateMetrics();
|
||||||
|
|
||||||
|
inline bool handleEvent( QEvent* event )
|
||||||
|
{
|
||||||
|
return this->event( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
void geometryChange(
|
||||||
|
const QRectF& newGeometry, const QRectF& oldGeometry ) override
|
||||||
|
{
|
||||||
|
Inherited::geometryChange( newGeometry, oldGeometry );
|
||||||
|
updateClip();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void geometryChanged(
|
||||||
|
const QRectF& newGeometry, const QRectF& oldGeometry ) override
|
||||||
|
{
|
||||||
|
Inherited::geometryChanged( newGeometry, oldGeometry );
|
||||||
|
updateClip();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void updateClip()
|
||||||
|
{
|
||||||
|
setClip( ( contentWidth() > width() ) ||
|
||||||
|
( contentHeight() > height() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* updatePaintNode(
|
||||||
|
QSGNode* oldNode, UpdatePaintNodeData* data ) override
|
||||||
|
{
|
||||||
|
updateColors();
|
||||||
|
return Inherited::updatePaintNode( oldNode, data );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QuickTextInput::QuickTextInput( QskTextInput* textInput )
|
||||||
|
: QQuickTextInput( textInput )
|
||||||
|
{
|
||||||
|
classBegin();
|
||||||
|
|
||||||
|
setActiveFocusOnTab( false );
|
||||||
|
setFlag( ItemAcceptsInputMethod, false );
|
||||||
|
setFocusOnPress( false );
|
||||||
|
|
||||||
|
componentComplete();
|
||||||
|
|
||||||
|
connect( this, &QQuickTextInput::contentSizeChanged,
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
auto textInput = static_cast< const QskTextInput* >( parentItem() );
|
||||||
|
|
||||||
|
setAlignment( textInput->alignment() );
|
||||||
|
setFont( textInput->font() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTextInput::updateColors()
|
||||||
|
{
|
||||||
|
auto textInput = static_cast< const QskTextInput* >( parentItem() );
|
||||||
|
auto d = QQuickTextInputPrivate::get( this );
|
||||||
|
|
||||||
|
bool isDirty = false;
|
||||||
|
|
||||||
|
QColor color;
|
||||||
|
|
||||||
|
color = textInput->color( QskTextInput::Text );
|
||||||
|
if ( d->color != color )
|
||||||
|
{
|
||||||
|
d->color = color;
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( d->hasSelectedText() )
|
||||||
|
{
|
||||||
|
QskAspect::States states = QskTextInputSkinlet::Selected;
|
||||||
|
#if 0
|
||||||
|
states |= textInput->skinStates();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
color = textInput->color( QskTextInput::TextPanel | states );
|
||||||
|
if ( d->selectionColor != color )
|
||||||
|
{
|
||||||
|
d->selectionColor = color;
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = textInput->color( QskTextInput::Text | states );
|
||||||
|
if ( d->selectedTextColor != color )
|
||||||
|
{
|
||||||
|
d->selectedTextColor = color;
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isDirty )
|
||||||
|
{
|
||||||
|
d->textLayoutDirty = true;
|
||||||
|
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
So QskTextInput is more or less a simple wrapper making everything
|
||||||
|
conforming to qskinny.
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_data->wrappedInput = new QuickTextInput( this );
|
||||||
|
qskBindSignals( m_data->wrappedInput, this );
|
||||||
|
|
||||||
|
setAcceptedMouseButtons( m_data->wrappedInput->acceptedMouseButtons() );
|
||||||
|
m_data->wrappedInput->setAcceptedMouseButtons( Qt::NoButton );
|
||||||
|
|
||||||
|
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
if ( hasAcceptableInput() || fixup() )
|
||||||
|
{
|
||||||
|
QGuiApplication::inputMethod()->commit();
|
||||||
|
|
||||||
|
if ( !( inputMethodHints() & Qt::ImhMultiLine ) )
|
||||||
|
{
|
||||||
|
setEditing( false );
|
||||||
|
|
||||||
|
// When returning from a virtual keyboard
|
||||||
|
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
case Qt::Key_Escape:
|
||||||
|
{
|
||||||
|
setEditing( false );
|
||||||
|
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->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 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
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() );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setMaxLength( int length )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setMaxLength( length );
|
||||||
|
}
|
||||||
|
|
||||||
|
QValidator* QskTextInput::validator() const
|
||||||
|
{
|
||||||
|
return m_data->wrappedInput->validator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setValidator( QValidator* validator )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setValidator( validator );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QskTextInput::inputMask() const
|
||||||
|
{
|
||||||
|
return m_data->wrappedInput->inputMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setInputMask( const QString& mask )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setInputMask( mask );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskTextInput::EchoMode QskTextInput::echoMode() const
|
||||||
|
{
|
||||||
|
const auto mode = m_data->wrappedInput->echoMode();
|
||||||
|
return static_cast< QskTextInput::EchoMode >( mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setEchoMode( EchoMode mode )
|
||||||
|
{
|
||||||
|
if ( mode != echoMode() )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setEchoMode(
|
||||||
|
static_cast< QQuickTextInput::EchoMode >( mode ) );
|
||||||
|
|
||||||
|
qskUpdateInputMethod( this, Qt::ImHints );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QskTextInput::passwordCharacter() const
|
||||||
|
{
|
||||||
|
return m_data->wrappedInput->passwordCharacter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setPasswordCharacter( const QString& text )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setPasswordCharacter( text );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::resetPasswordCharacter()
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setPasswordCharacter(
|
||||||
|
QGuiApplication::styleHints()->passwordMaskCharacter() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QskTextInput::passwordMaskDelay() const
|
||||||
|
{
|
||||||
|
return m_data->wrappedInput->passwordMaskDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setPasswordMaskDelay( int ms )
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->setPasswordMaskDelay( ms );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::resetPasswordMaskDelay()
|
||||||
|
{
|
||||||
|
m_data->wrappedInput->resetPasswordMaskDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskTextInput::fixup()
|
||||||
|
{
|
||||||
|
return m_data->wrappedInput->fixup();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QskTextInput::inputMethodQuery(
|
||||||
|
Qt::InputMethodQuery property ) const
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskTextInput::setupFrom( const QQuickItem* item )
|
||||||
|
{
|
||||||
|
if ( item == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// finding attributes from the input hints of item
|
||||||
|
|
||||||
|
int maxCharacters = 32767;
|
||||||
|
QskTextInput::EchoMode echoMode = QskTextInput::Normal;
|
||||||
|
|
||||||
|
Qt::InputMethodQueries queries = Qt::ImQueryAll;
|
||||||
|
queries &= ~Qt::ImEnabled;
|
||||||
|
|
||||||
|
QInputMethodQueryEvent event( queries );
|
||||||
|
QCoreApplication::sendEvent( const_cast< QQuickItem* >( item ), &event );
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImHints )
|
||||||
|
{
|
||||||
|
const auto hints = static_cast< Qt::InputMethodHints >(
|
||||||
|
event.value( Qt::ImHints ).toInt() );
|
||||||
|
|
||||||
|
if ( hints & Qt::ImhHiddenText )
|
||||||
|
echoMode = QskTextInput::NoEcho;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImMaximumTextLength )
|
||||||
|
{
|
||||||
|
// needs to be handled before Qt::ImCursorPosition !
|
||||||
|
|
||||||
|
const auto max = event.value( Qt::ImMaximumTextLength ).toInt();
|
||||||
|
maxCharacters = qBound( 0, max, maxCharacters );
|
||||||
|
}
|
||||||
|
|
||||||
|
setMaxLength( maxCharacters );
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImSurroundingText )
|
||||||
|
{
|
||||||
|
const auto text = event.value( Qt::ImSurroundingText ).toString();
|
||||||
|
setText( text );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImCursorPosition )
|
||||||
|
{
|
||||||
|
const auto pos = event.value( Qt::ImCursorPosition ).toInt();
|
||||||
|
setCursorPosition( pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImCurrentSelection )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
const auto text = event.value( Qt::ImCurrentSelection ).toString();
|
||||||
|
if ( !text.isEmpty() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int passwordMaskDelay = -1;
|
||||||
|
QString passwordCharacter;
|
||||||
|
|
||||||
|
if ( echoMode == QskTextInput::NoEcho )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Qt::ImhHiddenText does not provide information
|
||||||
|
to decide between NoEcho/Password, or provides
|
||||||
|
more details about how to deal with hidden inputs.
|
||||||
|
So we try to find out more from trying some properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QVariant value;
|
||||||
|
|
||||||
|
value = item->property( "passwordMaskDelay" );
|
||||||
|
if ( value.canConvert< int >() )
|
||||||
|
passwordMaskDelay = value.toInt();
|
||||||
|
|
||||||
|
value = item->property( "passwordCharacter" );
|
||||||
|
if ( value.canConvert< QString >() )
|
||||||
|
passwordCharacter = value.toString();
|
||||||
|
|
||||||
|
value = item->property( "echoMode" );
|
||||||
|
if ( value.canConvert< int >() )
|
||||||
|
{
|
||||||
|
const auto mode = value.toInt();
|
||||||
|
if ( mode == QskTextInput::Password )
|
||||||
|
echoMode = QskTextInput::Password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( passwordMaskDelay >= 0 )
|
||||||
|
setPasswordMaskDelay( passwordMaskDelay );
|
||||||
|
else
|
||||||
|
resetPasswordMaskDelay();
|
||||||
|
|
||||||
|
if ( !passwordCharacter.isEmpty() )
|
||||||
|
setPasswordCharacter( passwordCharacter );
|
||||||
|
else
|
||||||
|
resetPasswordCharacter();
|
||||||
|
|
||||||
|
setEchoMode( echoMode );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_QskTextInput.cpp"
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_TEXT_INPUT_H
|
||||||
|
#define QSK_TEXT_INPUT_H
|
||||||
|
|
||||||
|
#include "QskControl.h"
|
||||||
|
#include "QskTextOptions.h"
|
||||||
|
|
||||||
|
class QValidator;
|
||||||
|
class QskFontRole;
|
||||||
|
|
||||||
|
class QSK_EXPORT QskTextInput : public QskControl
|
||||||
|
{
|
||||||
|
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 )
|
||||||
|
|
||||||
|
Q_PROPERTY( QString passwordCharacter READ passwordCharacter
|
||||||
|
WRITE setPasswordCharacter RESET resetPasswordCharacter
|
||||||
|
NOTIFY passwordCharacterChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( int passwordMaskDelay READ passwordMaskDelay
|
||||||
|
WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay
|
||||||
|
NOTIFY passwordMaskDelayChanged )
|
||||||
|
|
||||||
|
using Inherited = QskControl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSK_SUBCONTROLS( TextPanel, Text )
|
||||||
|
|
||||||
|
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 )
|
||||||
|
|
||||||
|
enum EchoMode : quint8
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
NoEcho,
|
||||||
|
Password,
|
||||||
|
PasswordEchoOnEdit
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_ENUM( EchoMode )
|
||||||
|
|
||||||
|
~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;
|
||||||
|
|
||||||
|
bool isEditing() const;
|
||||||
|
|
||||||
|
QFont font() const;
|
||||||
|
|
||||||
|
bool isReadOnly() const;
|
||||||
|
void setReadOnly( bool );
|
||||||
|
|
||||||
|
int cursorPosition() const;
|
||||||
|
void setCursorPosition( int );
|
||||||
|
|
||||||
|
int maxLength() const;
|
||||||
|
void setMaxLength( int );
|
||||||
|
|
||||||
|
QValidator* validator() const;
|
||||||
|
void setValidator( QValidator* );
|
||||||
|
|
||||||
|
QString inputMask() const;
|
||||||
|
void setInputMask( const QString& );
|
||||||
|
|
||||||
|
EchoMode echoMode() const;
|
||||||
|
void setEchoMode( EchoMode );
|
||||||
|
|
||||||
|
QString passwordCharacter() const;
|
||||||
|
void setPasswordCharacter( const QString& );
|
||||||
|
void resetPasswordCharacter();
|
||||||
|
|
||||||
|
int passwordMaskDelay() const;
|
||||||
|
void setPasswordMaskDelay( int );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
void ensureVisible( int position );
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
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 );
|
||||||
|
void passwordMaskDelayChanged();
|
||||||
|
void passwordCharacterChanged();
|
||||||
|
|
||||||
|
void validatorChanged();
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PrivateData;
|
||||||
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextInput::ActivationModes )
|
||||||
|
Q_DECLARE_METATYPE( QskTextInput::ActivationModes )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskTextInputSkinlet.h"
|
||||||
|
#include "QskTextInput.h"
|
||||||
|
|
||||||
|
#include <qfontmetrics.h>
|
||||||
|
|
||||||
|
using Q = QskTextInput;
|
||||||
|
|
||||||
|
QSK_SYSTEM_STATE( QskTextInputSkinlet, Selected, QskAspect::FirstSystemState << 3 )
|
||||||
|
|
||||||
|
QskTextInputSkinlet::QskTextInputSkinlet( QskSkin* skin )
|
||||||
|
: Inherited( skin )
|
||||||
|
{
|
||||||
|
setNodeRoles( { TextPanelRole } );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskTextInputSkinlet::~QskTextInputSkinlet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskTextInputSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
if ( subControl == Q::TextPanel )
|
||||||
|
return contentsRect;
|
||||||
|
|
||||||
|
if ( subControl == Q::Text )
|
||||||
|
{
|
||||||
|
auto rect = skinnable->subControlContentsRect( contentsRect, Q::TextPanel );
|
||||||
|
|
||||||
|
const auto h = skinnable->effectiveFontHeight( Q::Text );
|
||||||
|
rect.setTop( rect.center().y() - 0.5 * h );
|
||||||
|
rect.setHeight( h );
|
||||||
|
rect = rect.marginsAdded( skinnable->marginHint( Q::Text ) );
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* QskTextInputSkinlet::updateSubNode(
|
||||||
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
switch ( nodeRole )
|
||||||
|
{
|
||||||
|
case TextPanelRole:
|
||||||
|
return updateBoxNode( skinnable, node, Q::TextPanel );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF QskTextInputSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
|
Qt::SizeHint which, const QSizeF& ) const
|
||||||
|
{
|
||||||
|
if ( which != Qt::PreferredSize )
|
||||||
|
return QSizeF();
|
||||||
|
|
||||||
|
const auto text = static_cast< const QskTextInput* >( skinnable )->text();
|
||||||
|
|
||||||
|
const QFontMetricsF fm( skinnable->effectiveFont( Q::Text ) );
|
||||||
|
|
||||||
|
auto hint = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, text );
|
||||||
|
|
||||||
|
hint = skinnable->outerBoxSize( Q::TextPanel, hint );
|
||||||
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::TextPanel ) );
|
||||||
|
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_TEXT_INPUT_SKINLET_H
|
||||||
|
#define QSK_TEXT_INPUT_SKINLET_H
|
||||||
|
|
||||||
|
#include "QskSkinlet.h"
|
||||||
|
|
||||||
|
class QSK_EXPORT QskTextInputSkinlet : public QskSkinlet
|
||||||
|
{
|
||||||
|
using Inherited = QskSkinlet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSK_STATES( Selected )
|
||||||
|
|
||||||
|
enum NodeRole : quint8
|
||||||
|
{
|
||||||
|
TextPanelRole,
|
||||||
|
RoleCount
|
||||||
|
};
|
||||||
|
|
||||||
|
~QskTextInputSkinlet() override;
|
||||||
|
|
||||||
|
QRectF subControlRect( const QskSkinnable*,
|
||||||
|
const QRectF& rect, QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
QSizeF sizeHint( const QskSkinnable*,
|
||||||
|
Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QskTextInputSkinlet( QskSkin* = nullptr );
|
||||||
|
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -32,7 +32,7 @@ namespace
|
||||||
QskAspect::Subcontrol substitutedSubcontrol(
|
QskAspect::Subcontrol substitutedSubcontrol(
|
||||||
QskAspect::Subcontrol subControl ) const override
|
QskAspect::Subcontrol subControl ) const override
|
||||||
{
|
{
|
||||||
if ( subControl == QskTextField::Panel )
|
if ( subControl == QskTextField::TextPanel )
|
||||||
return m_panelBox->effectiveSubcontrol( QskInputPanelBox::ProxyPanel );
|
return m_panelBox->effectiveSubcontrol( QskInputPanelBox::ProxyPanel );
|
||||||
|
|
||||||
if ( subControl == QskTextField::Text )
|
if ( subControl == QskTextField::Text )
|
||||||
|
|
@ -184,7 +184,7 @@ QskAspect::Subcontrol QskInputPanelBox::substitutedSubcontrol(
|
||||||
#if 1
|
#if 1
|
||||||
// TODO ...
|
// TODO ...
|
||||||
if ( subControl == QskInputPanelBox::ProxyPanel )
|
if ( subControl == QskInputPanelBox::ProxyPanel )
|
||||||
return QskTextField::Panel;
|
return QskTextField::TextPanel;
|
||||||
|
|
||||||
if ( subControl == QskInputPanelBox::ProxyText )
|
if ( subControl == QskInputPanelBox::ProxyText )
|
||||||
return QskTextField::Text;
|
return QskTextField::Text;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue