QskAbstractTextInputSkinlet instead of QskTextInputSkinlet/QskTextEditSkinlet

This commit is contained in:
Uwe Rathmann 2025-01-30 12:49:54 +01:00
parent 5af007cf4a
commit 3fbd18456e
15 changed files with 177 additions and 288 deletions

View File

@ -76,8 +76,10 @@ namespace
field->setText( "John Doe" );
field->setPlaceholderText( "<Name>" );
connect( field, &QskTextField::textChanged,
[field]() { qDebug() << "Text:" << field->text(); } );
#if 0
connect( field, &QskTextField::textChanged,
[field]() { qDebug() << "Text:" << field->text(); } );
#endif
}
@ -107,11 +109,11 @@ connect( field, &QskTextField::textChanged,
setSpacing( 20 );
{
auto textArea = new QskTextArea( "here enter longer text", this );
auto textArea = new QskTextArea( "here enter longer text\nwith multiple lines", this );
textArea->setWrapMode( QskTextOptions::Wrap );
textArea->setPlaceholderText( "placeholder text" );
#if 1
#if 0
connect( textArea, &QskTextArea::textChanged,
this, [textArea]() { qDebug() << "Text:" << textArea->text(); } );
#endif
@ -200,12 +202,6 @@ void InputPage::syncValues( qreal value )
auto sliders = findChildren< QskSlider* >();
for ( auto slider : sliders )
slider->setValue( value );
#if 1
auto textEdits = findChildren< QskTextEdit* >();
for ( auto edit : textEdits )
edit->setText( QString::number( value ) );
#endif
}
blockUpdates = false;

View File

@ -198,6 +198,7 @@ endif()
list(APPEND HEADERS
controls/QskAbstractButton.h
controls/QskAbstractTextInput.h
controls/QskAbstractTextInputSkinlet.h
controls/QskAnimationHint.h
controls/QskAnimator.h
controls/QskMainView.h
@ -287,11 +288,9 @@ list(APPEND HEADERS
controls/QskTextArea.h
controls/QskTextAreaSkinlet.h
controls/QskTextEdit.h
controls/QskTextEditSkinlet.h
controls/QskTextField.h
controls/QskTextFieldSkinlet.h
controls/QskTextInput.h
controls/QskTextInputSkinlet.h
controls/QskTextLabel.h
controls/QskTextLabelSkinlet.h
controls/QskVariantAnimator.h
@ -308,6 +307,7 @@ list(APPEND PRIVATE_HEADERS
list(APPEND SOURCES
controls/QskAbstractButton.cpp
controls/QskAbstractTextInput.cpp
controls/QskAbstractTextInputSkinlet.cpp
controls/QskAnimator.cpp
controls/QskAnimationHint.cpp
controls/QskMainView.cpp
@ -400,11 +400,9 @@ list(APPEND SOURCES
controls/QskTextArea.cpp
controls/QskTextAreaSkinlet.cpp
controls/QskTextEdit.cpp
controls/QskTextEditSkinlet.cpp
controls/QskTextField.cpp
controls/QskTextFieldSkinlet.cpp
controls/QskTextInput.cpp
controls/QskTextInputSkinlet.cpp
controls/QskTextLabel.cpp
controls/QskTextLabelSkinlet.cpp
controls/QskVariantAnimator.cpp

View File

@ -24,11 +24,24 @@ QSK_QT_PRIVATE_BEGIN
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskAbstractTextInput, Text )
QSK_SUBCONTROL( QskAbstractTextInput, TextPanel )
QSK_SYSTEM_STATE( QskAbstractTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Editing, QskAspect::FirstSystemState << 2 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Selected, QskAspect::FirstSystemState << 3 )
/*
QQuickText-Edit/Input are beasts of several thousands lines of code,
we can't ( and don't want to ) reimplement them.
Instead we implement wrappers with some extra functionality to
have it in line with the QSkinny framework.
For some reason Qt development decided not to introduce a common
base class for QQuickText-Edit/input and implemented large parts
of the API twice. To avoid that we also have to copy those parts to our
wrappers we need the ugly implementation you find in this file.
*/
static inline QVariant qskInputMethodQuery(
const QQuickItem* item, Qt::InputMethodQuery query, QVariant argument )
{
@ -109,12 +122,14 @@ class QskAbstractTextInput::PrivateData
#define INPUT_INVOKE_ARG(func, arg) \
( m_data->textInput ? m_data->textInput->func( arg ) : m_data->textEdit->func( arg ) )
#define INPUT_CONNECT( func ) \
#define INPUT_CONNECT2( func1, func2 ) \
m_data->textInput \
? connect( m_data->textInput, &QQuickTextInput::func, this, &QskAbstractTextInput::func ) \
: connect( m_data->textEdit, &QQuickTextEdit::func, this, &QskAbstractTextInput::func )
? connect( m_data->textInput, &QQuickTextInput::func1, this, &QskAbstractTextInput::func2 ) \
: connect( m_data->textEdit, &QQuickTextEdit::func1, this, &QskAbstractTextInput::func2 )
#define INPUT_CONNECT1( func, get ) \
#define INPUT_CONNECT1( func ) INPUT_CONNECT2( func, func )
#define INPUT_CONNECT_ARG( func, get ) \
do \
{ \
auto f = [this]() { Q_EMIT func( get() ); }; \
@ -148,22 +163,24 @@ void QskAbstractTextInput::setup( QQuickItem* wrappedInput )
m_data->textInput = qobject_cast< QQuickTextInput* >( wrappedInput );
m_data->textEdit = qobject_cast< QQuickTextEdit* >( wrappedInput );
INPUT_CONNECT( textChanged );
INPUT_CONNECT( preeditTextChanged );
INPUT_CONNECT( readOnlyChanged );
INPUT_CONNECT( overwriteModeChanged );
INPUT_CONNECT( cursorVisibleChanged );
INPUT_CONNECT1( cursorPositionChanged, cursorPosition );
INPUT_CONNECT( selectByMouseChanged );
INPUT_CONNECT1( persistentSelectionChanged, persistentSelection );
INPUT_CONNECT1( wrapModeChanged, wrapMode );
INPUT_CONNECT1( textChanged );
INPUT_CONNECT1( preeditTextChanged );
INPUT_CONNECT1( selectedTextChanged );
INPUT_CONNECT1( readOnlyChanged );
INPUT_CONNECT1( overwriteModeChanged );
INPUT_CONNECT1( cursorVisibleChanged );
INPUT_CONNECT_ARG( cursorPositionChanged, cursorPosition );
INPUT_CONNECT1( selectByMouseChanged );
INPUT_CONNECT_ARG( persistentSelectionChanged, persistentSelection );
INPUT_CONNECT_ARG( wrapModeChanged, wrapMode );
INPUT_CONNECT2( contentSizeChanged, resetImplicitSize );
INPUT_CONNECT1( canUndoChanged, canUndo );
INPUT_CONNECT1( canRedoChanged, canRedo );
INPUT_CONNECT1( canPasteChanged, canPaste );
INPUT_CONNECT_ARG( canUndoChanged, canUndo );
INPUT_CONNECT_ARG( canRedoChanged, canRedo );
INPUT_CONNECT_ARG( canPasteChanged, canPaste );
INPUT_CONNECT1( inputMethodHintsChanged, inputMethodHints );
INPUT_CONNECT1( inputMethodComposingChanged, isInputMethodComposing );
INPUT_CONNECT_ARG( inputMethodHintsChanged, inputMethodHints );
INPUT_CONNECT_ARG( inputMethodComposingChanged, isInputMethodComposing );
/*
Other properties offered from QQuickTextInput/QQuickTextEdit:
@ -196,9 +213,8 @@ void QskAbstractTextInput::setup( QQuickItem* wrappedInput )
- selectionStartChanged;
- selectionEndChanged;
- selectedTextChanged;
Maybe there is a better API for the selection TODO ...
Do we need this ?
- mouseSelectionModeChanged
@ -208,7 +224,7 @@ void QskAbstractTextInput::setup( QQuickItem* wrappedInput )
This signal should never be emitted as it happens on
events ( focusOut, commit keys ) that are handled in
QskAbstractTextInput and indicated with editicgChanged( bool );
QskAbstractTextInput and are indicated with editingChanged( bool );
( Maybe having an assertion TODO ... )
- contentSizeChanged
@ -239,46 +255,59 @@ void QskAbstractTextInput::setActivationModes( ActivationModes modes )
}
}
#if 1
// stupid code forwarding calls 1:1 to the wrapped item
bool QskAbstractTextInput::selectByMouse() const
{
return INPUT_INVOKE( selectByMouse );
}
{ return INPUT_INVOKE( selectByMouse ); }
void QskAbstractTextInput::setSelectByMouse( bool on )
{
INPUT_INVOKE_ARG( setSelectByMouse, on );
}
{ INPUT_INVOKE_ARG( setSelectByMouse, on ); }
bool QskAbstractTextInput::persistentSelection() const
{
return INPUT_INVOKE( persistentSelection );
}
{ return INPUT_INVOKE( persistentSelection ); }
void QskAbstractTextInput::setPersistentSelection( bool on )
{
INPUT_INVOKE_ARG( setPersistentSelection, on );
}
{ INPUT_INVOKE_ARG( setPersistentSelection, on ); }
int QskAbstractTextInput::length() const
{
return INPUT_INVOKE( length );
}
{ return INPUT_INVOKE( length ); }
QString QskAbstractTextInput::text() const
{
return INPUT_INVOKE( text );
}
{ return INPUT_INVOKE( text ); }
void QskAbstractTextInput::setText( const QString& text )
{
INPUT_INVOKE_ARG( setText, text );
}
{ INPUT_INVOKE_ARG( setText, text ); }
QString QskAbstractTextInput::preeditText() const
{
return INPUT_INVOKE( preeditText );
}
{ return INPUT_INVOKE( preeditText ); }
QString QskAbstractTextInput::selectedText() const
{ return INPUT_INVOKE( selectedText ); }
bool QskAbstractTextInput::isInputMethodComposing() const
{ return INPUT_INVOKE( isInputMethodComposing ); }
bool QskAbstractTextInput::overwriteMode() const
{ return INPUT_INVOKE( overwriteMode ); }
void QskAbstractTextInput::setOverwriteMode( bool on )
{ INPUT_INVOKE_ARG( setOverwriteMode, on ); }
int QskAbstractTextInput::cursorPosition() const
{ return INPUT_INVOKE( cursorPosition ); }
void QskAbstractTextInput::setCursorPosition( int pos )
{ INPUT_INVOKE_ARG( setCursorPosition, pos ); }
bool QskAbstractTextInput::isCursorVisible() const
{ return INPUT_INVOKE( isCursorVisible ); }
void QskAbstractTextInput::setCursorVisible( bool on )
{ INPUT_INVOKE_ARG( setCursorVisible, on ); }
bool QskAbstractTextInput::isReadOnly() const { return INPUT_INVOKE( isReadOnly ); }
bool QskAbstractTextInput::canUndo() const { return INPUT_INVOKE( canUndo ); }
bool QskAbstractTextInput::canRedo() const { return INPUT_INVOKE( canRedo ); }
bool QskAbstractTextInput::canPaste() const { return INPUT_INVOKE( canPaste ); }
@ -292,6 +321,14 @@ void QskAbstractTextInput::paste() { INPUT_INVOKE( paste ); }
void QskAbstractTextInput::undo() { INPUT_INVOKE( undo ); }
void QskAbstractTextInput::redo() { INPUT_INVOKE( redo ); }
#endif
bool QskAbstractTextInput::hasSelectedText() const
{
return INPUT_INVOKE( selectionEnd ) > INPUT_INVOKE( selectionStart );
}
void QskAbstractTextInput::setFontRole( const QskFontRole& role )
{
if ( setFontRoleHint( Text, role ) )
@ -546,11 +583,6 @@ void QskAbstractTextInput::inputMethodEvent( QInputMethodEvent* event )
}
}
bool QskAbstractTextInput::isReadOnly() const
{
return INPUT_INVOKE( isReadOnly );
}
void QskAbstractTextInput::setReadOnly( bool on )
{
if ( on == isReadOnly() )
@ -575,11 +607,6 @@ void QskAbstractTextInput::setReadOnly( bool on )
setSkinStateFlag( ReadOnly, on );
}
bool QskAbstractTextInput::isInputMethodComposing() const
{
return INPUT_INVOKE( isInputMethodComposing );
}
bool QskAbstractTextInput::isEditing() const
{
return hasSkinState( Editing );
@ -599,36 +626,6 @@ void QskAbstractTextInput::setEditing( bool on )
Q_EMIT editingChanged( on );
}
bool QskAbstractTextInput::overwriteMode() const
{
return INPUT_INVOKE( overwriteMode );
}
void QskAbstractTextInput::setOverwriteMode( bool on )
{
INPUT_INVOKE_ARG( setOverwriteMode, on );
}
int QskAbstractTextInput::cursorPosition() const
{
return INPUT_INVOKE( cursorPosition );
}
void QskAbstractTextInput::setCursorPosition( int pos )
{
INPUT_INVOKE_ARG( setCursorPosition, pos );
}
bool QskAbstractTextInput::isCursorVisible() const
{
return INPUT_INVOKE( isCursorVisible );
}
void QskAbstractTextInput::setCursorVisible( bool on )
{
INPUT_INVOKE_ARG( setCursorVisible, on );
}
void QskAbstractTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
{
if ( m_data->textInput )
@ -664,12 +661,12 @@ void QskAbstractTextInput::setTextColor( const QColor& color )
if ( setColor( Text, color ) )
Q_EMIT textColorChanged( color );
}
void QskAbstractTextInput::resetTextColor()
{
if ( resetColor( Text ) )
Q_EMIT textColorChanged( color( Text ) );
}
}
QColor QskAbstractTextInput::textColor() const
{

View File

@ -23,6 +23,9 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl
Q_PROPERTY( QString preeditText READ preeditText
NOTIFY preeditTextChanged )
Q_PROPERTY( QString selectedText READ selectedText
NOTIFY selectedTextChanged )
Q_PROPERTY( bool editing READ isEditing
WRITE setEditing NOTIFY editingChanged )
@ -71,7 +74,7 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl
using Inherited = QskControl;
public:
QSK_SUBCONTROLS( Text )
QSK_SUBCONTROLS( Text, TextPanel )
QSK_STATES( ReadOnly, Editing, Selected )
enum ActivationMode
@ -93,6 +96,8 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl
QString text() const;
QString preeditText() const;
QString selectedText() const;
bool hasSelectedText() const;
int length() const;
@ -182,6 +187,7 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl
void inputMethodComposingChanged( bool );
void textChanged();
void selectedTextChanged();
void textEdited( const QString& );
void preeditTextChanged();

View File

@ -3,24 +3,22 @@
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskTextInputSkinlet.h"
#include "QskTextInput.h"
#include "QskAbstractTextInputSkinlet.h"
#include "QskAbstractTextInput.h"
#include <qfontmetrics.h>
using Q = QskAbstractTextInput;
using Q = QskTextInput;
QskTextInputSkinlet::QskTextInputSkinlet( QskSkin* skin )
QskAbstractTextInputSkinlet::QskAbstractTextInputSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { TextPanelRole } );
}
QskTextInputSkinlet::~QskTextInputSkinlet()
QskAbstractTextInputSkinlet::~QskAbstractTextInputSkinlet()
{
}
QRectF QskTextInputSkinlet::subControlRect( const QskSkinnable* skinnable,
QRectF QskAbstractTextInputSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
if ( subControl == Q::TextPanel )
@ -29,10 +27,6 @@ QRectF QskTextInputSkinlet::subControlRect( const QskSkinnable* skinnable,
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;
@ -41,7 +35,7 @@ QRectF QskTextInputSkinlet::subControlRect( const QskSkinnable* skinnable,
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskTextInputSkinlet::updateSubNode(
QSGNode* QskAbstractTextInputSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
switch ( nodeRole )
@ -53,24 +47,21 @@ QSGNode* QskTextInputSkinlet::updateSubNode(
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSizeF QskTextInputSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const
QSizeF QskAbstractTextInputSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& constraint ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
const auto textInput = static_cast< const QskTextInput* >( skinnable );
Q_UNUSED( constraint ); // TODO ...
const QFontMetricsF fm( skinnable->effectiveFont( Q::Text ) );
const auto input = static_cast< const QskAbstractTextInput* >( skinnable );
#if 0
auto hint = QSizeF( textInput->unwrappedTextSize().width(), fm.height() );
#else
auto hint = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, textInput->text() );
#endif
hint = skinnable->outerBoxSize( Q::TextPanel, hint );
hint = hint.expandedTo( skinnable->strutSizeHint( Q::TextPanel ) );
auto hint = input->unwrappedTextSize();
hint = input->outerBoxSize( Q::TextPanel, hint );
hint = hint.expandedTo( input->strutSizeHint( Q::TextPanel ) );
return hint;
}
#include "moc_QskAbstractTextInputSkinlet.cpp"

View File

@ -3,13 +3,15 @@
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_TEXT_EDIT_SKINLET_H
#define QSK_TEXT_EDIT_SKINLET_H
#ifndef QSK_ABSTRACT_TEXT_INPUT_SKINLET_H
#define QSK_ABSTRACT_TEXT_INPUT_SKINLET_H
#include "QskSkinlet.h"
class QSK_EXPORT QskTextEditSkinlet : public QskSkinlet
class QSK_EXPORT QskAbstractTextInputSkinlet : public QskSkinlet
{
Q_GADGET
using Inherited = QskSkinlet;
public:
@ -19,7 +21,8 @@ class QSK_EXPORT QskTextEditSkinlet : public QskSkinlet
RoleCount
};
~QskTextEditSkinlet() override;
Q_INVOKABLE QskAbstractTextInputSkinlet( QskSkin* = nullptr );
~QskAbstractTextInputSkinlet() override;
QRectF subControlRect( const QskSkinnable*,
const QRectF& rect, QskAspect::Subcontrol ) const override;
@ -28,8 +31,6 @@ class QSK_EXPORT QskTextEditSkinlet : public QskSkinlet
Qt::SizeHint, const QSizeF& ) const override;
protected:
QskTextEditSkinlet( QskSkin* = nullptr );
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
};

View File

@ -25,6 +25,9 @@
#include <cmath>
#include "QskAbstractTextInput.h"
#include "QskAbstractTextInputSkinlet.h"
#include "QskBox.h"
#include "QskBoxSkinlet.h"
@ -103,9 +106,6 @@
#include "QskTextArea.h"
#include "QskTextAreaSkinlet.h"
#include "QskTextEdit.h"
#include "QskTextEditSkinlet.h"
#include "QskTextField.h"
#include "QskTextFieldSkinlet.h"
@ -194,6 +194,7 @@ QskSkin::QskSkin( QObject* parent )
{
declareSkinlet< QskControl, QskSkinlet >();
declareSkinlet< QskAbstractTextInput, QskAbstractTextInputSkinlet >();
declareSkinlet< QskBox, QskBoxSkinlet >();
declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >();
declareSkinlet< QskComboBox, QskComboBoxSkinlet >();

View File

@ -6,15 +6,15 @@
#ifndef QSK_TEXT_AREA_SKINLET_H
#define QSK_TEXT_AREA_SKINLET_H
#include "QskTextEditSkinlet.h"
#include "QskAbstractTextInputSkinlet.h"
class QskTextArea;
class QSK_EXPORT QskTextAreaSkinlet : public QskTextEditSkinlet
class QSK_EXPORT QskTextAreaSkinlet : public QskAbstractTextInputSkinlet
{
Q_GADGET
using Inherited = QskTextEditSkinlet;
using Inherited = QskAbstractTextInputSkinlet;
public:
enum NodeRole : quint8

View File

@ -12,6 +12,7 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquicktextedit_p_p.h>
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskTextEdit, Text )
QSK_SUBCONTROL( QskTextEdit, TextPanel )
/*
@ -139,24 +140,25 @@ QskTextEdit::QskTextEdit( QQuickItem* parent )
, m_data( new PrivateData() )
{
m_data->wrappedEdit = new QuickTextEdit( this );
auto wrappedEdit = m_data->wrappedEdit;
setAcceptedMouseButtons( m_data->wrappedEdit->acceptedMouseButtons() );
m_data->wrappedEdit->setAcceptedMouseButtons( Qt::NoButton );
setAcceptedMouseButtons( wrappedEdit->acceptedMouseButtons() );
wrappedEdit->setAcceptedMouseButtons( Qt::NoButton );
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
setup( m_data->wrappedEdit );
setup( wrappedEdit );
connect( m_data->wrappedEdit, &QQuickTextEdit::lineCountChanged,
connect( wrappedEdit, &QQuickTextEdit::lineCountChanged,
this, [this]() { Q_EMIT lineCountChanged( lineCount() ); } );
connect( m_data->wrappedEdit, &QQuickTextEdit::linkActivated,
connect( wrappedEdit, &QQuickTextEdit::linkActivated,
this, &QskTextEdit::linkActivated );
connect( m_data->wrappedEdit, &QQuickTextEdit::linkHovered,
connect( wrappedEdit, &QQuickTextEdit::linkHovered,
this, &QskTextEdit::linkHovered );
connect( m_data->wrappedEdit, &QQuickTextEdit::linkActivated,
connect( wrappedEdit, &QQuickTextEdit::linkActivated,
this, &QskTextEdit::linkActivated );
}
@ -164,6 +166,18 @@ QskTextEdit::~QskTextEdit()
{
}
QskAspect::Subcontrol QskTextEdit::substitutedSubcontrol(
QskAspect::Subcontrol subControl ) const
{
if ( subControl == Inherited::Text )
return Text;
if ( subControl == Inherited::TextPanel )
return TextPanel;
return Inherited::substitutedSubcontrol( subControl );
}
QUrl QskTextEdit::baseUrl() const
{
return m_data->wrappedEdit->baseUrl();

View File

@ -27,7 +27,7 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
using Inherited = QskAbstractTextInput;
public:
QSK_SUBCONTROLS( TextPanel )
QSK_SUBCONTROLS( Text, TextPanel )
QskTextEdit( QQuickItem* parent = nullptr );
~QskTextEdit() override;
@ -54,6 +54,10 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
void linkHovered( const QString& );
void linkActivated( const QString& );
protected:
QskAspect::Subcontrol substitutedSubcontrol(
QskAspect::Subcontrol ) const override;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;

View File

@ -1,88 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskTextEditSkinlet.h"
#include "QskTextEdit.h"
#include <qfontmetrics.h>
using Q = QskTextEdit;
QskTextEditSkinlet::QskTextEditSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { TextPanelRole } );
}
QskTextEditSkinlet::~QskTextEditSkinlet()
{
}
QRectF QskTextEditSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
if ( subControl == Q::TextPanel )
{
return contentsRect;
}
else if ( subControl == Q::Text )
{
auto rect = skinnable->subControlContentsRect( contentsRect, Q::TextPanel );
rect = rect.marginsAdded( skinnable->marginHint( Q::Text ) );
return rect;
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskTextEditSkinlet::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 QskTextEditSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
const auto textEdit = static_cast< const QskTextEdit* >( skinnable );
const QFontMetricsF fm( textEdit->effectiveFont( Q::Text ) );
int flags = Qt::TextExpandTabs;
const auto wm = textEdit->wrapMode();
if( wm & QskTextOptions::WordWrap )
{
flags |= Qt::TextWordWrap;
}
else if( wm & QskTextOptions::WrapAnywhere )
{
flags |= Qt::TextWrapAnywhere;
}
else if( wm & QskTextOptions::Wrap )
{
flags |= Qt::TextWordWrap | Qt::TextWrapAnywhere;
}
auto hint = fm.boundingRect( textEdit->subControlRect( Q::Text ), flags, textEdit->text() ).size();
hint = textEdit->outerBoxSize( Q::TextPanel, hint );
hint = hint.expandedTo( textEdit->strutSizeHint( Q::TextPanel ) );
return hint;
}

View File

@ -6,20 +6,20 @@
#ifndef QSK_TEXT_FIELD_SKINLET_H
#define QSK_TEXT_FIELD_SKINLET_H
#include "QskTextInputSkinlet.h"
#include "QskAbstractTextInputSkinlet.h"
class QskTextField;
class QSK_EXPORT QskTextFieldSkinlet : public QskTextInputSkinlet
class QSK_EXPORT QskTextFieldSkinlet : public QskAbstractTextInputSkinlet
{
Q_GADGET
using Inherited = QskTextInputSkinlet;
using Inherited = QskAbstractTextInputSkinlet;
public:
enum NodeRole : quint8
{
PanelRole = QskTextInputSkinlet::RoleCount,
PanelRole = QskAbstractTextInputSkinlet::RoleCount,
PlaceholderTextRole,
RoleCount

View File

@ -12,6 +12,7 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquicktextinput_p_p.h>
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskTextInput, Text )
QSK_SUBCONTROL( QskTextInput, TextPanel )
QSK_SYSTEM_STATE( QskTextInput, Error, QskAspect::FirstSystemState << 4 )
@ -154,13 +155,6 @@ QskTextInput::QskTextInput( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
/*
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 );
auto wrappedInput = m_data->wrappedInput;
@ -171,7 +165,6 @@ QskTextInput::QskTextInput( QQuickItem* parent )
setup( wrappedInput );
#if 1
connect( wrappedInput, &QQuickTextInput::maximumLengthChanged,
this, &QskTextInput::maximumLengthChanged );
@ -183,14 +176,24 @@ QskTextInput::QskTextInput( QQuickItem* parent )
connect( wrappedInput, &QQuickTextInput::acceptableInputChanged,
this, [this]() { Q_EMIT acceptableInputChanged( hasAcceptableInput() ); } );
#endif
}
QskTextInput::~QskTextInput()
{
}
QskAspect::Subcontrol QskTextInput::substitutedSubcontrol(
QskAspect::Subcontrol subControl ) const
{
if ( subControl == Inherited::Text )
return Text;
if ( subControl == Inherited::TextPanel )
return TextPanel;
return Inherited::substitutedSubcontrol( subControl );
}
void QskTextInput::ensureVisible( int position )
{
m_data->wrappedInput->ensureVisible( position );

View File

@ -46,8 +46,7 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput
using Inherited = QskAbstractTextInput;
public:
QSK_SUBCONTROLS( TextPanel )
QSK_SUBCONTROLS( Text, TextPanel )
QSK_STATES( Error )
enum EchoMode : quint8
@ -108,6 +107,10 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput
void displayTextChanged();
protected:
QskAspect::Subcontrol substitutedSubcontrol(
QskAspect::Subcontrol ) const override;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;

View File

@ -1,37 +0,0 @@
/******************************************************************************
* 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:
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