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

View File

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

View File

@ -24,11 +24,24 @@ QSK_QT_PRIVATE_BEGIN
QSK_QT_PRIVATE_END QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskAbstractTextInput, Text ) QSK_SUBCONTROL( QskAbstractTextInput, Text )
QSK_SUBCONTROL( QskAbstractTextInput, TextPanel )
QSK_SYSTEM_STATE( QskAbstractTextInput, ReadOnly, QskAspect::FirstSystemState << 1 ) QSK_SYSTEM_STATE( QskAbstractTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Editing, QskAspect::FirstSystemState << 2 ) QSK_SYSTEM_STATE( QskAbstractTextInput, Editing, QskAspect::FirstSystemState << 2 )
QSK_SYSTEM_STATE( QskAbstractTextInput, Selected, QskAspect::FirstSystemState << 3 ) 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( static inline QVariant qskInputMethodQuery(
const QQuickItem* item, Qt::InputMethodQuery query, QVariant argument ) const QQuickItem* item, Qt::InputMethodQuery query, QVariant argument )
{ {
@ -109,12 +122,14 @@ class QskAbstractTextInput::PrivateData
#define INPUT_INVOKE_ARG(func, arg) \ #define INPUT_INVOKE_ARG(func, arg) \
( m_data->textInput ? m_data->textInput->func( arg ) : m_data->textEdit->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 \ m_data->textInput \
? connect( m_data->textInput, &QQuickTextInput::func, this, &QskAbstractTextInput::func ) \ ? connect( m_data->textInput, &QQuickTextInput::func1, this, &QskAbstractTextInput::func2 ) \
: connect( m_data->textEdit, &QQuickTextEdit::func, this, &QskAbstractTextInput::func ) : 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 \ do \
{ \ { \
auto f = [this]() { Q_EMIT func( get() ); }; \ 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->textInput = qobject_cast< QQuickTextInput* >( wrappedInput );
m_data->textEdit = qobject_cast< QQuickTextEdit* >( wrappedInput ); m_data->textEdit = qobject_cast< QQuickTextEdit* >( wrappedInput );
INPUT_CONNECT( textChanged ); INPUT_CONNECT1( textChanged );
INPUT_CONNECT( preeditTextChanged ); INPUT_CONNECT1( preeditTextChanged );
INPUT_CONNECT( readOnlyChanged ); INPUT_CONNECT1( selectedTextChanged );
INPUT_CONNECT( overwriteModeChanged ); INPUT_CONNECT1( readOnlyChanged );
INPUT_CONNECT( cursorVisibleChanged ); INPUT_CONNECT1( overwriteModeChanged );
INPUT_CONNECT1( cursorPositionChanged, cursorPosition ); INPUT_CONNECT1( cursorVisibleChanged );
INPUT_CONNECT( selectByMouseChanged ); INPUT_CONNECT_ARG( cursorPositionChanged, cursorPosition );
INPUT_CONNECT1( persistentSelectionChanged, persistentSelection ); INPUT_CONNECT1( selectByMouseChanged );
INPUT_CONNECT1( wrapModeChanged, wrapMode ); INPUT_CONNECT_ARG( persistentSelectionChanged, persistentSelection );
INPUT_CONNECT_ARG( wrapModeChanged, wrapMode );
INPUT_CONNECT2( contentSizeChanged, resetImplicitSize );
INPUT_CONNECT1( canUndoChanged, canUndo ); INPUT_CONNECT_ARG( canUndoChanged, canUndo );
INPUT_CONNECT1( canRedoChanged, canRedo ); INPUT_CONNECT_ARG( canRedoChanged, canRedo );
INPUT_CONNECT1( canPasteChanged, canPaste ); INPUT_CONNECT_ARG( canPasteChanged, canPaste );
INPUT_CONNECT1( inputMethodHintsChanged, inputMethodHints ); INPUT_CONNECT_ARG( inputMethodHintsChanged, inputMethodHints );
INPUT_CONNECT1( inputMethodComposingChanged, isInputMethodComposing ); INPUT_CONNECT_ARG( inputMethodComposingChanged, isInputMethodComposing );
/* /*
Other properties offered from QQuickTextInput/QQuickTextEdit: Other properties offered from QQuickTextInput/QQuickTextEdit:
@ -196,9 +213,8 @@ void QskAbstractTextInput::setup( QQuickItem* wrappedInput )
- selectionStartChanged; - selectionStartChanged;
- selectionEndChanged; - selectionEndChanged;
- selectedTextChanged;
Maybe there is a better API for the selection TODO ... Do we need this ?
- mouseSelectionModeChanged - mouseSelectionModeChanged
@ -208,7 +224,7 @@ void QskAbstractTextInput::setup( QQuickItem* wrappedInput )
This signal should never be emitted as it happens on This signal should never be emitted as it happens on
events ( focusOut, commit keys ) that are handled in 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 ... ) ( Maybe having an assertion TODO ... )
- contentSizeChanged - 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 bool QskAbstractTextInput::selectByMouse() const
{ { return INPUT_INVOKE( selectByMouse ); }
return INPUT_INVOKE( selectByMouse );
}
void QskAbstractTextInput::setSelectByMouse( bool on ) void QskAbstractTextInput::setSelectByMouse( bool on )
{ { INPUT_INVOKE_ARG( setSelectByMouse, on ); }
INPUT_INVOKE_ARG( setSelectByMouse, on );
}
bool QskAbstractTextInput::persistentSelection() const bool QskAbstractTextInput::persistentSelection() const
{ { return INPUT_INVOKE( persistentSelection ); }
return INPUT_INVOKE( persistentSelection );
}
void QskAbstractTextInput::setPersistentSelection( bool on ) void QskAbstractTextInput::setPersistentSelection( bool on )
{ { INPUT_INVOKE_ARG( setPersistentSelection, on ); }
INPUT_INVOKE_ARG( setPersistentSelection, on );
}
int QskAbstractTextInput::length() const int QskAbstractTextInput::length() const
{ { return INPUT_INVOKE( length ); }
return INPUT_INVOKE( length );
}
QString QskAbstractTextInput::text() const QString QskAbstractTextInput::text() const
{ { return INPUT_INVOKE( text ); }
return INPUT_INVOKE( text );
}
void QskAbstractTextInput::setText( const QString& text ) void QskAbstractTextInput::setText( const QString& text )
{ { INPUT_INVOKE_ARG( setText, text ); }
INPUT_INVOKE_ARG( setText, text );
}
QString QskAbstractTextInput::preeditText() const 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::canUndo() const { return INPUT_INVOKE( canUndo ); }
bool QskAbstractTextInput::canRedo() const { return INPUT_INVOKE( canRedo ); } bool QskAbstractTextInput::canRedo() const { return INPUT_INVOKE( canRedo ); }
bool QskAbstractTextInput::canPaste() const { return INPUT_INVOKE( canPaste ); } 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::undo() { INPUT_INVOKE( undo ); }
void QskAbstractTextInput::redo() { INPUT_INVOKE( redo ); } void QskAbstractTextInput::redo() { INPUT_INVOKE( redo ); }
#endif
bool QskAbstractTextInput::hasSelectedText() const
{
return INPUT_INVOKE( selectionEnd ) > INPUT_INVOKE( selectionStart );
}
void QskAbstractTextInput::setFontRole( const QskFontRole& role ) void QskAbstractTextInput::setFontRole( const QskFontRole& role )
{ {
if ( setFontRoleHint( Text, 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 ) void QskAbstractTextInput::setReadOnly( bool on )
{ {
if ( on == isReadOnly() ) if ( on == isReadOnly() )
@ -575,11 +607,6 @@ void QskAbstractTextInput::setReadOnly( bool on )
setSkinStateFlag( ReadOnly, on ); setSkinStateFlag( ReadOnly, on );
} }
bool QskAbstractTextInput::isInputMethodComposing() const
{
return INPUT_INVOKE( isInputMethodComposing );
}
bool QskAbstractTextInput::isEditing() const bool QskAbstractTextInput::isEditing() const
{ {
return hasSkinState( Editing ); return hasSkinState( Editing );
@ -599,36 +626,6 @@ void QskAbstractTextInput::setEditing( bool on )
Q_EMIT editingChanged( 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 ) void QskAbstractTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
{ {
if ( m_data->textInput ) if ( m_data->textInput )
@ -664,12 +661,12 @@ void QskAbstractTextInput::setTextColor( const QColor& color )
if ( setColor( Text, color ) ) if ( setColor( Text, color ) )
Q_EMIT textColorChanged( color ); Q_EMIT textColorChanged( color );
} }
void QskAbstractTextInput::resetTextColor() void QskAbstractTextInput::resetTextColor()
{ {
if ( resetColor( Text ) ) if ( resetColor( Text ) )
Q_EMIT textColorChanged( color( Text ) ); Q_EMIT textColorChanged( color( Text ) );
} }
QColor QskAbstractTextInput::textColor() const QColor QskAbstractTextInput::textColor() const
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
using Inherited = QskAbstractTextInput; using Inherited = QskAbstractTextInput;
public: public:
QSK_SUBCONTROLS( TextPanel ) QSK_SUBCONTROLS( Text, TextPanel )
QskTextEdit( QQuickItem* parent = nullptr ); QskTextEdit( QQuickItem* parent = nullptr );
~QskTextEdit() override; ~QskTextEdit() override;
@ -54,6 +54,10 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
void linkHovered( const QString& ); void linkHovered( const QString& );
void linkActivated( const QString& ); void linkActivated( const QString& );
protected:
QskAspect::Subcontrol substitutedSubcontrol(
QskAspect::Subcontrol ) const override;
private: private:
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; 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 #ifndef QSK_TEXT_FIELD_SKINLET_H
#define QSK_TEXT_FIELD_SKINLET_H #define QSK_TEXT_FIELD_SKINLET_H
#include "QskTextInputSkinlet.h" #include "QskAbstractTextInputSkinlet.h"
class QskTextField; class QskTextField;
class QSK_EXPORT QskTextFieldSkinlet : public QskTextInputSkinlet class QSK_EXPORT QskTextFieldSkinlet : public QskAbstractTextInputSkinlet
{ {
Q_GADGET Q_GADGET
using Inherited = QskTextInputSkinlet; using Inherited = QskAbstractTextInputSkinlet;
public: public:
enum NodeRole : quint8 enum NodeRole : quint8
{ {
PanelRole = QskTextInputSkinlet::RoleCount, PanelRole = QskAbstractTextInputSkinlet::RoleCount,
PlaceholderTextRole, PlaceholderTextRole,
RoleCount RoleCount

View File

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

View File

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