diff --git a/examples/gallery/inputs/InputPage.cpp b/examples/gallery/inputs/InputPage.cpp index cdd9deaa..4487fb18 100644 --- a/examples/gallery/inputs/InputPage.cpp +++ b/examples/gallery/inputs/InputPage.cpp @@ -75,6 +75,10 @@ namespace auto field = new QskTextField( this ); field->setText( "John Doe" ); field->setPlaceholderText( "" ); + +connect( field, &QskTextField::textChanged, + []( const QString& text ) { qDebug() << "Text:" << text; } ); + } { @@ -106,6 +110,11 @@ namespace auto textArea = new QskTextArea( "here enter longer text", this ); textArea->setWrapMode( QskTextOptions::Wrap ); textArea->setPlaceholderText( "placeholder text" ); + +#if 1 + connect( textArea, &QskTextArea::textChanged, + []( const QString& text ) { qDebug() << "Text:" << text; } ); +#endif } } }; @@ -191,6 +200,12 @@ 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; diff --git a/src/controls/QskAbstractTextInput.cpp b/src/controls/QskAbstractTextInput.cpp index dd59ae9c..530d755a 100644 --- a/src/controls/QskAbstractTextInput.cpp +++ b/src/controls/QskAbstractTextInput.cpp @@ -119,6 +119,92 @@ static inline void qskForwardEvent( QQuickItem* item, QEvent* event ) } } +static inline bool qskIsIrrelevantProperty( const char* name ) +{ + static const char* properties[] = + { + /* + these are properties that are set from skin hints. + do we want to have convenience setters/getters for these hints ? + */ + "color", + "selectionColor", + "selectedTextColor", + + /* + covered by the alignment property + */ + "horizontalAlignment", + "effectiveHorizontalAlignment", + "verticalAlignment", + + /* + we don't want to offer cursorDelegates as this would be done + using subcontrols. + */ + "cursorRectangle", + "cursorDelegate", + + /* + hasSelectedText ? + */ + "selectionStart", + "selectionEnd", + "selectedText", + + /* + covered by QskAbstractTextInput::ActivationMode + */ + + "activeFocusOnPress", + + /* + These poperties correspond to Qt::TextInteractionFlags + we can't simply forward them as mouseSelectionMode returns + local enums of QQuickTextEdit and QQuickTextInput + */ + "selectByMouse", + "selectByKeyboard", + "mouseSelectionMode", + + /* + covered by unwrappedTextSize + */ + "contentWidth", + "contentHeight", + "paintedWidth", + "paintedHeight", + + /* + unused we have our own padding from the skin hints + */ + "padding", + "topPadding", + "leftPadding", + "rightPadding", + "bottomPadding", + + /* + ends up in QTextDocument::documentMargin. But how is its + effect different to what you get from the padding ? + */ + "textMargin", + + /* + not covered so far, but IMHO of little relevance + */ + "renderType" + }; + + for ( const auto n : properties ) + { + if ( strcmp( name, n ) == 0 ) + return true; + } + + return false; +} + namespace { class PropertyBinder : public QObject @@ -167,7 +253,8 @@ namespace } else { - // qDebug() << "Missing" << property.name(); + if ( !qskIsIrrelevantProperty( property.name() ) ) + qDebug() << "Missing:" << mo->className() << property.name(); } } } @@ -197,6 +284,11 @@ namespace const auto property = mo->property( binding.first ); const auto value = property.read( sender() ); +#if 0 + qDebug() << property.name() << value + << binding.second.methodSignature(); +#endif + void* args[3] = { nullptr, const_cast< void* >( value.data() ), nullptr }; qskInvokeMetaMethod( parent(), binding.second, args, Qt::DirectConnection ); @@ -270,6 +362,21 @@ void QskAbstractTextInput::setSelectByMouse( bool on ) m_data->input->setProperty( "selectByMouse", on ); } +bool QskAbstractTextInput::persistentSelection() const +{ + return m_data->input->property( "persistentSelection" ).value< bool >(); +} + +void QskAbstractTextInput::setPersistentSelection( bool on ) +{ + m_data->input->setProperty( "persistentSelection", on ); +} + +int QskAbstractTextInput::length() const +{ + return m_data->input->property( "length" ).value< int >(); +} + QString QskAbstractTextInput::text() const { return m_data->input->property( "text" ).value< QString >(); @@ -310,6 +417,11 @@ bool QskAbstractTextInput::canRedo() const return m_data->input->property( "canRedo" ).value< bool >(); } +bool QskAbstractTextInput::canPaste() const +{ + return m_data->input->property( "canPaste" ).value< bool >(); +} + void QskAbstractTextInput::setFontRole( const QskFontRole& role ) { if ( setFontRoleHint( Text, role ) ) @@ -580,6 +692,11 @@ void QskAbstractTextInput::setReadOnly( bool on ) setSkinStateFlag( ReadOnly, on ); } +bool QskAbstractTextInput::isInputMethodComposing() const +{ + return m_data->input->property( "inputMethodComposing" ).value< bool >(); +} + bool QskAbstractTextInput::isEditing() const { return hasSkinState( Editing ); @@ -667,6 +784,14 @@ QskTextOptions::WrapMode QskAbstractTextInput::wrapMode() const return static_cast< QskTextOptions::WrapMode >( mode ); } +QSizeF QskAbstractTextInput::unwrappedTextSize() const +{ + const auto w = m_data->input->property( "contentWidth" ).value< qreal >(); + const auto h = m_data->input->property( "contentHeight" ).value< qreal >(); + + return QSizeF( w, h ); +} + void QskAbstractTextInput::setAlignment( Qt::Alignment alignment ) { if ( setAlignmentHint( Text, alignment ) ) diff --git a/src/controls/QskAbstractTextInput.h b/src/controls/QskAbstractTextInput.h index 4d205e83..8417e84d 100644 --- a/src/controls/QskAbstractTextInput.h +++ b/src/controls/QskAbstractTextInput.h @@ -18,6 +18,8 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged USER true ) + Q_PROPERTY( int length READ length NOTIFY lengthChanged ) + Q_PROPERTY( QString preeditText READ preeditText NOTIFY preeditTextChanged ) @@ -30,6 +32,12 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl Q_PROPERTY( ActivationModes activationModes READ activationModes WRITE setActivationModes NOTIFY activationModesChanged ) + Q_PROPERTY( Qt::InputMethodHints inputMethodHints READ inputMethodHints + WRITE setInputMethodHints NOTIFY inputMethodHintsChanged ) + + Q_PROPERTY( bool inputMethodComposing READ isInputMethodComposing + NOTIFY inputMethodComposingChanged ) + Q_PROPERTY( QskFontRole fontRole READ fontRole WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged ) @@ -50,11 +58,12 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged ) - Q_PROPERTY( bool selectByMouse READ selectByMouse - WRITE setSelectByMouse NOTIFY selectByMouseChanged ) + Q_PROPERTY( bool persistentSelection READ persistentSelection + WRITE setPersistentSelection NOTIFY persistentSelectionChanged ) Q_PROPERTY( bool canUndo READ canUndo NOTIFY canUndoChanged ) Q_PROPERTY( bool canRedo READ canRedo NOTIFY canRedoChanged ) + Q_PROPERTY( bool canPaste READ canPaste NOTIFY canPasteChanged ) using Inherited = QskControl; @@ -82,10 +91,13 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl QString text() const; QString preeditText() const; + int length() const; + bool isReadOnly() const; void setReadOnly( bool ); bool isEditing() const; + bool isInputMethodComposing() const; void setActivationModes( ActivationModes ); ActivationModes activationModes() const; @@ -93,6 +105,9 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl void setSelectByMouse( bool ); bool selectByMouse() const; + void setPersistentSelection( bool ); + bool persistentSelection() const; + void setAlignment( Qt::Alignment ); void resetAlignment(); Qt::Alignment alignment() const; @@ -123,6 +138,9 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl bool canUndo() const; bool canRedo() const; + bool canPaste() const; + + QSizeF unwrappedTextSize() const; public Q_SLOTS: void setText( const QString& ); @@ -136,15 +154,20 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl void editingChanged( bool ); void readOnlyChanged( bool ); void activationModesChanged(); + void inputMethodHintsChanged( Qt::InputMethodHints ); void fontRoleChanged(); void overwriteModeChanged( bool ); void cursorPositionChanged( int ); void cursorVisibleChanged( bool ); void selectByMouseChanged( bool ); + void persistentSelectionChanged( bool ); void wrapModeChanged( QskTextOptions::WrapMode ); void alignmentChanged(); + void inputMethodComposingChanged( bool ); + + void lengthChanged( int ); void textChanged( const QString& ); void textEdited( const QString& ); void displayTextChanged( const QString& ); @@ -153,6 +176,7 @@ class QSK_EXPORT QskAbstractTextInput : public QskControl #if 1 void canUndoChanged( bool ); void canRedoChanged( bool ); + void canPasteChanged( bool ); #endif protected: diff --git a/src/controls/QskTextEdit.cpp b/src/controls/QskTextEdit.cpp index 1dd0d501..c4eb0643 100644 --- a/src/controls/QskTextEdit.cpp +++ b/src/controls/QskTextEdit.cpp @@ -130,6 +130,26 @@ QskTextEdit::~QskTextEdit() { } +QUrl QskTextEdit::baseUrl() const +{ + return m_data->wrappedEdit->baseUrl(); +} + +void QskTextEdit::setBaseUrl( const QUrl& url ) +{ + m_data->wrappedEdit->setBaseUrl( url ); +} + +void QskTextEdit::resetBaseUrl() +{ + m_data->wrappedEdit->resetBaseUrl(); +} + +QString QskTextEdit::hoveredLink() const +{ + return m_data->wrappedEdit->hoveredLink(); +} + void QskTextEdit::setTextFormat( QskTextOptions::TextFormat textFormat ) { m_data->wrappedEdit->setTextFormat( diff --git a/src/controls/QskTextEdit.h b/src/controls/QskTextEdit.h index 91788df8..6f0dfc22 100644 --- a/src/controls/QskTextEdit.h +++ b/src/controls/QskTextEdit.h @@ -21,6 +21,11 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput Q_PROPERTY( qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance NOTIFY tabStopDistanceChanged ) + Q_PROPERTY( QUrl baseUrl READ baseUrl WRITE setBaseUrl + RESET resetBaseUrl NOTIFY baseUrlChanged ) + + Q_PROPERTY( QString hoveredLink READ hoveredLink NOTIFY linkHovered ) + using Inherited = QskAbstractTextInput; public: @@ -37,12 +42,21 @@ class QSK_EXPORT QskTextEdit : public QskAbstractTextInput int tabStopDistance() const; void setTabStopDistance( qreal ); + QUrl baseUrl() const; + void setBaseUrl( const QUrl& ); + void resetBaseUrl(); + + QString hoveredLink() const; + Q_SIGNALS: void lineCountChanged( int ); + void baseUrlChanged( QUrl ); void textFormatChanged( QskTextOptions::TextFormat ); void tabStopDistanceChanged( qreal ); + void linkHovered( const QString& ); + private: class PrivateData; std::unique_ptr< PrivateData > m_data; diff --git a/src/controls/QskTextInput.cpp b/src/controls/QskTextInput.cpp index f968e863..aef2f21f 100644 --- a/src/controls/QskTextInput.cpp +++ b/src/controls/QskTextInput.cpp @@ -184,6 +184,16 @@ void QskTextInput::setInputMask( const QString& mask ) m_data->wrappedInput->setInputMask( mask ); } +bool QskTextInput::autoScroll() const +{ + return m_data->wrappedInput->autoScroll(); +} + +void QskTextInput::setAutoScroll( bool on ) +{ + m_data->wrappedInput->setAutoScroll( on ); +} + QskTextInput::EchoMode QskTextInput::echoMode() const { const auto mode = m_data->wrappedInput->echoMode(); diff --git a/src/controls/QskTextInput.h b/src/controls/QskTextInput.h index 2cfb7138..15706cf9 100644 --- a/src/controls/QskTextInput.h +++ b/src/controls/QskTextInput.h @@ -15,6 +15,20 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput { Q_OBJECT + Q_PROPERTY( QString displayText READ displayText NOTIFY displayTextChanged ) + + Q_PROPERTY( int maximumLength READ maxLength + WRITE setMaxLength NOTIFY maximumLengthChanged ) + + Q_PROPERTY( QString inputMask READ inputMask + WRITE setInputMask NOTIFY inputMaskChanged ) + + Q_PROPERTY( bool acceptableInput READ hasAcceptableInput + NOTIFY acceptableInputChanged) + + Q_PROPERTY( bool autoScroll READ autoScroll + WRITE setAutoScroll NOTIFY autoScrollChanged ) + Q_PROPERTY( EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged ) @@ -26,6 +40,9 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay NOTIFY passwordMaskDelayChanged ) + Q_PROPERTY( QValidator* validator READ validator + WRITE setValidator NOTIFY validatorChanged ) + using Inherited = QskAbstractTextInput; public: @@ -55,6 +72,9 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput QString inputMask() const; void setInputMask( const QString& ); + bool autoScroll() const; + void setAutoScroll( bool ); + EchoMode echoMode() const; void setEchoMode( EchoMode ); @@ -77,12 +97,17 @@ class QSK_EXPORT QskTextInput : public QskAbstractTextInput Q_SIGNALS: void maximumLengthChanged( int ); + void autoScrollChanged( bool ); + void echoModeChanged( EchoMode ); void passwordMaskDelayChanged(); void passwordCharacterChanged(); - void validatorChanged(); + void validatorChanged( const QValidator* ); void inputMaskChanged( const QString& ); + void acceptableInputChanged( bool ); + + void displayTextChanged( const QString& ); private: class PrivateData; diff --git a/src/controls/QskTextInputSkinlet.cpp b/src/controls/QskTextInputSkinlet.cpp index 6991d4b4..edb41bc3 100644 --- a/src/controls/QskTextInputSkinlet.cpp +++ b/src/controls/QskTextInputSkinlet.cpp @@ -59,11 +59,15 @@ QSizeF QskTextInputSkinlet::sizeHint( const QskSkinnable* skinnable, if ( which != Qt::PreferredSize ) return QSizeF(); - const auto text = static_cast< const QskTextInput* >( skinnable )->text(); + const auto textInput = static_cast< const QskTextInput* >( skinnable ); const QFontMetricsF fm( skinnable->effectiveFont( Q::Text ) ); - auto hint = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, text ); +#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 ) );