QskAbstractTextInput introduced - trying to bring the implementation of
QskTextEdit/QskTextInput together. work in progress
This commit is contained in:
parent
4fa3c6e5b7
commit
4fb9819767
|
|
@ -299,11 +299,8 @@ namespace
|
|||
void setupTabViewMetrics();
|
||||
void setupTabViewColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
||||
template< typename Q >
|
||||
void setupTextControlMetrics();
|
||||
|
||||
template< typename Q, typename SK >
|
||||
void setupTextControlColors( QskAspect::Section section, const QskFluent2Theme& theme );
|
||||
void setupTextInputMetrics();
|
||||
void setupTextInputColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
||||
void setupTextAreaMetrics();
|
||||
void setupTextAreaColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
|
@ -367,6 +364,7 @@ void Editor::setupMetrics()
|
|||
setupTabButtonMetrics();
|
||||
setupTabBarMetrics();
|
||||
setupTabViewMetrics();
|
||||
setupTextInputMetrics();
|
||||
setupTextAreaMetrics();
|
||||
setupTextFieldMetrics();
|
||||
setupTextLabelMetrics();
|
||||
|
|
@ -407,6 +405,7 @@ void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& the
|
|||
setupTabButtonColors( section, theme );
|
||||
setupTabBarColors( section, theme );
|
||||
setupTabViewColors( section, theme );
|
||||
setupTextInputColors( section, theme );
|
||||
setupTextAreaColors( section, theme );
|
||||
setupTextFieldColors( section, theme );
|
||||
setupTextLabelColors( section, theme );
|
||||
|
|
@ -1794,8 +1793,34 @@ void Editor::setupTextLabelColors(
|
|||
setColor( Q::Text | section, pal.fillColor.text.primary );
|
||||
}
|
||||
|
||||
template< typename Q > void Editor::setupTextControlMetrics()
|
||||
void Editor::setupTextInputMetrics()
|
||||
{
|
||||
using Q = QskAbstractTextInput;
|
||||
setFontRole( Q::Text, Fluent2::Body );
|
||||
}
|
||||
|
||||
void Editor::setupTextInputColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||
{
|
||||
using Q = QskAbstractTextInput;
|
||||
|
||||
const auto& pal = theme.palette;
|
||||
|
||||
const auto text = Q::Text | section;
|
||||
|
||||
#if 1
|
||||
setColor( text, pal.fillColor.text.primary );
|
||||
setColor( text | Q::Selected, pal.fillColor.textOnAccent.selectedText );
|
||||
setColor( text | Q::Disabled, pal.fillColor.text.disabled );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Editor::setupTextAreaMetrics()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
|
||||
// ===
|
||||
|
||||
setStrutSize( Q::TextPanel, { -1, 30_px } );
|
||||
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
||||
|
||||
|
|
@ -1805,97 +1830,123 @@ template< typename Q > void Editor::setupTextControlMetrics()
|
|||
|
||||
setBoxShape( Q::TextPanel, 3_px );
|
||||
|
||||
setFontRole( Q::Text, Fluent2::Body );
|
||||
|
||||
setAlignment( Q::Placeholder, alignment( Q::Text ) );
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
|
||||
setFontRole( Q::Placeholder, fontRole( Q::Text ) );
|
||||
}
|
||||
|
||||
template< typename Q, typename SK > void Editor::setupTextControlColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme)
|
||||
void Editor::setupTextAreaColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskTextArea;
|
||||
|
||||
const auto& pal = theme.palette;
|
||||
|
||||
setColor( Q::TextPanel | SK::Selected, pal.fillColor.accent.selectedTextBackground );
|
||||
setColor( Q::Text | SK::Selected, pal.fillColor.textOnAccent.selectedText );
|
||||
setColor( Q::TextPanel | Q::Selected, pal.fillColor.accent.selectedTextBackground );
|
||||
setColor( Q::Placeholder, pal.fillColor.text.secondary );
|
||||
|
||||
for( const auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Editing, Q::Disabled } )
|
||||
{
|
||||
QRgb panelColor, borderColor1, borderColor2, textColor;
|
||||
QRgb panelColor, borderColor1, borderColor2;
|
||||
|
||||
if ( state == A::NoState )
|
||||
{
|
||||
panelColor = pal.fillColor.control.defaultColor;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.elevation.textControl.border[1];
|
||||
textColor = pal.fillColor.text.primary;
|
||||
}
|
||||
else if ( state == Q::Hovered )
|
||||
{
|
||||
panelColor = pal.fillColor.control.secondary;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.elevation.textControl.border[1];
|
||||
textColor = pal.fillColor.text.primary;
|
||||
}
|
||||
else if ( ( state == Q::Focused ) || ( state == Q::Editing ) )
|
||||
{
|
||||
panelColor = pal.fillColor.control.inputActive;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.fillColor.accent.defaultColor;
|
||||
textColor = pal.fillColor.text.primary;
|
||||
}
|
||||
else if ( state == Q::Disabled )
|
||||
{
|
||||
panelColor = pal.fillColor.control.disabled;
|
||||
borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor;
|
||||
textColor = pal.fillColor.text.disabled;
|
||||
}
|
||||
|
||||
const auto panel = Q::TextPanel | section | state;
|
||||
const auto text = Q::Text | section | state;
|
||||
|
||||
panelColor = rgbSolid( panelColor, pal.background.solid.base );
|
||||
|
||||
setGradient( panel, panelColor );
|
||||
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
|
||||
|
||||
setColor( text, textColor );
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::setupTextAreaMetrics()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
|
||||
|
||||
setupTextControlMetrics< Q >();
|
||||
}
|
||||
|
||||
void Editor::setupTextAreaColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||
{
|
||||
setupTextControlColors< QskTextArea, QskTextAreaSkinlet >( section, theme );
|
||||
}
|
||||
|
||||
void Editor::setupTextFieldMetrics()
|
||||
{
|
||||
using Q = QskTextField;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
// =============
|
||||
|
||||
setupTextControlMetrics< Q >();
|
||||
setStrutSize( Q::TextPanel, { -1, 30_px } );
|
||||
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
||||
|
||||
setBoxBorderMetrics( Q::TextPanel, 1_px );
|
||||
for( const auto& state : { Q::Focused, Q::Editing } )
|
||||
setBoxBorderMetrics( Q::TextPanel | state, { 1_px, 1_px, 1_px, 2_px } );
|
||||
|
||||
setBoxShape( Q::TextPanel, 3_px );
|
||||
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
setFontRole( Q::Placeholder, fontRole( Q::Text ) );
|
||||
}
|
||||
|
||||
void Editor::setupTextFieldColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||
{
|
||||
setupTextControlColors< QskTextField, QskTextFieldSkinlet >( section, theme );
|
||||
}
|
||||
using A = QskAspect;
|
||||
using Q = QskTextField;
|
||||
|
||||
const auto& pal = theme.palette;
|
||||
|
||||
setColor( Q::TextPanel | Q::Selected, pal.fillColor.accent.selectedTextBackground );
|
||||
setColor( Q::Placeholder, pal.fillColor.text.secondary );
|
||||
|
||||
for( const auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Editing, Q::Disabled } )
|
||||
{
|
||||
QRgb panelColor, borderColor1, borderColor2;
|
||||
|
||||
if ( state == A::NoState )
|
||||
{
|
||||
panelColor = pal.fillColor.control.defaultColor;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.elevation.textControl.border[1];
|
||||
}
|
||||
else if ( state == Q::Hovered )
|
||||
{
|
||||
panelColor = pal.fillColor.control.secondary;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.elevation.textControl.border[1];
|
||||
}
|
||||
else if ( ( state == Q::Focused ) || ( state == Q::Editing ) )
|
||||
{
|
||||
panelColor = pal.fillColor.control.inputActive;
|
||||
borderColor1 = pal.elevation.textControl.border[0];
|
||||
borderColor2 = pal.fillColor.accent.defaultColor;
|
||||
}
|
||||
else if ( state == Q::Disabled )
|
||||
{
|
||||
panelColor = pal.fillColor.control.disabled;
|
||||
borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor;
|
||||
}
|
||||
|
||||
const auto panel = Q::TextPanel | section | state;
|
||||
|
||||
panelColor = rgbSolid( panelColor, pal.background.solid.base );
|
||||
|
||||
setGradient( panel, panelColor );
|
||||
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
|
||||
}
|
||||
}
|
||||
void Editor::setupSwitchButtonMetrics()
|
||||
{
|
||||
using Q = QskSwitchButton;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@
|
|||
#include <QskTabButton.h>
|
||||
#include <QskTabView.h>
|
||||
#include <QskTextArea.h>
|
||||
#include <QskTextAreaSkinlet.h>
|
||||
#include <QskTextField.h>
|
||||
#include <QskTextFieldSkinlet.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskVirtualKeyboard.h>
|
||||
|
||||
|
|
@ -145,8 +143,7 @@ namespace
|
|||
Q_INVOKABLE void setupTabBar();
|
||||
Q_INVOKABLE void setupTabView();
|
||||
|
||||
template< typename Q, typename SK >
|
||||
void setupTextControl();
|
||||
Q_INVOKABLE void setupTextInput();
|
||||
Q_INVOKABLE void setupTextArea();
|
||||
Q_INVOKABLE void setupTextField();
|
||||
Q_INVOKABLE void setupTextLabel();
|
||||
|
|
@ -389,9 +386,29 @@ void Editor::setupTextLabel()
|
|||
setBoxBorderColors( Q::Panel, QskRgb::lighter( m_pal.outline, 108 ) );
|
||||
}
|
||||
|
||||
template< typename Q, typename SK >
|
||||
void Editor::setupTextControl()
|
||||
void Editor::setupTextInput()
|
||||
{
|
||||
using Q = QskAbstractTextInput;
|
||||
using A = QskAspect;
|
||||
using P = QPalette;
|
||||
|
||||
for ( auto state : { A::NoState, Q::Disabled } )
|
||||
{
|
||||
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
|
||||
|
||||
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
|
||||
setColor( Q::Text | Q::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::setupTextArea()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
|
||||
|
||||
// ========
|
||||
|
||||
using A = QskAspect;
|
||||
using P = QPalette;
|
||||
|
||||
|
|
@ -400,10 +417,8 @@ void Editor::setupTextControl()
|
|||
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
|
||||
|
||||
setColor( Q::TextPanel | state, m_pal.color( colorGroup, P::Base ) );
|
||||
setColor( Q::TextPanel | SK::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
|
||||
setColor( Q::TextPanel | Q::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
|
||||
|
||||
setColor( Q::Text | state, m_pal.color( colorGroup, P::Text ) );
|
||||
setColor( Q::Text | SK::Selected | state, m_pal.color( colorGroup, P::HighlightedText ) );
|
||||
setColor( Q::Placeholder, m_pal.color( colorGroup, P::PlaceholderText ) );
|
||||
}
|
||||
|
||||
|
|
@ -420,26 +435,38 @@ void Editor::setupTextControl()
|
|||
setPadding( Q::TextPanel, 4_px );
|
||||
}
|
||||
|
||||
void Editor::setupTextArea()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
using SK = QskTextAreaSkinlet;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
|
||||
|
||||
setupTextControl< Q, SK >();
|
||||
}
|
||||
|
||||
void Editor::setupTextField()
|
||||
{
|
||||
using Q = QskTextField;
|
||||
using SK = QskTextFieldSkinlet;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
||||
setupTextControl< Q, SK >();
|
||||
// ===
|
||||
|
||||
using A = QskAspect;
|
||||
using P = QPalette;
|
||||
|
||||
for ( auto state : { A::NoState, Q::Disabled } )
|
||||
{
|
||||
const auto colorGroup = ( state == A::NoState ) ? P::Active : P::Disabled;
|
||||
|
||||
setColor( Q::TextPanel | state, m_pal.color( colorGroup, P::Base ) );
|
||||
setColor( Q::TextPanel | Q::Selected | state, m_pal.color( colorGroup, P::Highlight ) );
|
||||
|
||||
setColor( Q::Placeholder, m_pal.color( colorGroup, P::PlaceholderText ) );
|
||||
}
|
||||
|
||||
setColor( Q::TextPanel | Q::ReadOnly, m_pal.disabled( P::Base ) );
|
||||
|
||||
setBoxBorderMetrics( Q::TextPanel, 1_px );
|
||||
|
||||
setBoxBorderColors( Q::TextPanel, m_pal.outline );
|
||||
#ifdef SHOW_FOCUS
|
||||
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.highlightedOutline );
|
||||
#endif
|
||||
|
||||
setBoxShape( Q::TextPanel, 2_px );
|
||||
setPadding( Q::TextPanel, 4_px );
|
||||
}
|
||||
|
||||
void Editor::setupProgressBar()
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "QskMaterial3ProgressBarSkinlet.h"
|
||||
#include "QskMaterial3SliderSkinlet.h"
|
||||
#include "QskMaterial3TextFieldSkinlet.h"
|
||||
#include <QskTextEditSkinlet.h>
|
||||
|
||||
#include <QskSkinHintTableEditor.h>
|
||||
|
||||
|
|
@ -188,8 +187,7 @@ namespace
|
|||
Q_INVOKABLE void setupTabBar();
|
||||
Q_INVOKABLE void setupTabView();
|
||||
|
||||
template< typename Q, typename SK >
|
||||
void setupTextControl();
|
||||
Q_INVOKABLE void setupTextInput();
|
||||
Q_INVOKABLE void setupTextArea();
|
||||
Q_INVOKABLE void setupTextField();
|
||||
Q_INVOKABLE void setupTextLabel();
|
||||
|
|
@ -437,13 +435,64 @@ void Editor::setupTextLabel()
|
|||
setPadding( Q::Panel, 5_px );
|
||||
}
|
||||
|
||||
template< typename Q, typename SK >
|
||||
void Editor::setupTextControl()
|
||||
void Editor::setupTextInput()
|
||||
{
|
||||
using Q = QskAbstractTextInput;
|
||||
|
||||
setColor( Q::Text, m_pal.onSurface );
|
||||
setFontRole( Q::Text, BodyLarge );
|
||||
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
|
||||
}
|
||||
|
||||
void Editor::setupTextArea()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
|
||||
// ==========
|
||||
|
||||
setStrutSize( Q::Panel, -1.0, 56_px );
|
||||
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
|
||||
setGradient( Q::Panel, m_pal.surfaceVariant );
|
||||
setColor( Q::TextPanel | SK::Selected, m_pal.primary12 );
|
||||
setColor( Q::TextPanel | Q::Selected, m_pal.primary12 );
|
||||
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
|
||||
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
|
||||
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
|
||||
setSpacing( Q::Panel, 8_px );
|
||||
|
||||
const auto hoverColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
m_pal.surfaceVariant, m_pal.hoverOpacity );
|
||||
setGradient( Q::Panel | Q::Hovered, hoverColor );
|
||||
|
||||
const auto focusColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
m_pal.surfaceVariant, m_pal.focusOpacity );
|
||||
setGradient( Q::Panel | Q::Focused, focusColor );
|
||||
|
||||
// ### Also add a pressed state
|
||||
|
||||
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
||||
const auto disabledPanelColor = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
|
||||
setGradient( Q::Panel | Q::Disabled, disabledPanelColor );
|
||||
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface38 );
|
||||
|
||||
// PlaceholderText
|
||||
|
||||
setColor( Q::Placeholder, color( Q::Text ) );
|
||||
setFontRole( Q::Placeholder, BodyLarge );
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignTop );
|
||||
}
|
||||
|
||||
void Editor::setupTextField()
|
||||
{
|
||||
using Q = QskTextField;
|
||||
|
||||
// ===
|
||||
|
||||
setStrutSize( Q::Panel, -1.0, 56_px );
|
||||
setPadding( Q::Panel, { 12_px, 8_px, 12_px, 8_px } );
|
||||
setGradient( Q::Panel, m_pal.surfaceVariant );
|
||||
setColor( Q::TextPanel | Q::Selected, m_pal.primary12 );
|
||||
setBoxShape( Q::Panel, m_pal.shapeExtraSmallTop );
|
||||
setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1_px } );
|
||||
setBoxBorderColors( Q::Panel, m_pal.onSurfaceVariant );
|
||||
|
|
@ -459,7 +508,6 @@ void Editor::setupTextControl()
|
|||
|
||||
// ### Also add a pressed state
|
||||
|
||||
setColor( Q::Text, m_pal.onSurface );
|
||||
setFontRole( Q::Text, BodyLarge );
|
||||
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
|
@ -468,33 +516,11 @@ void Editor::setupTextControl()
|
|||
setGradient( Q::Panel | Q::Disabled, disabledPanelColor );
|
||||
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface38 );
|
||||
|
||||
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
|
||||
|
||||
// PlaceholderText
|
||||
|
||||
setColor( Q::Placeholder, color( Q::Text ) );
|
||||
setFontRole( Q::Placeholder, BodyLarge );
|
||||
setAlignment( Q::Placeholder, alignment( Q::Text ) );
|
||||
}
|
||||
|
||||
void Editor::setupTextArea()
|
||||
{
|
||||
using Q = QskTextArea;
|
||||
using SK = QskTextEditSkinlet;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignTop );
|
||||
|
||||
setupTextControl< Q, SK >();
|
||||
}
|
||||
|
||||
void Editor::setupTextField()
|
||||
{
|
||||
using Q = QskTextField;
|
||||
using SK = QskTextInputSkinlet;
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
||||
setupTextControl< Q, SK >();
|
||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
}
|
||||
|
||||
void Editor::setupProgressBar()
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ endif()
|
|||
|
||||
list(APPEND HEADERS
|
||||
controls/QskAbstractButton.h
|
||||
controls/QskAbstractTextInput.h
|
||||
controls/QskAnimationHint.h
|
||||
controls/QskAnimator.h
|
||||
controls/QskMainView.h
|
||||
|
|
@ -306,6 +307,7 @@ list(APPEND PRIVATE_HEADERS
|
|||
|
||||
list(APPEND SOURCES
|
||||
controls/QskAbstractButton.cpp
|
||||
controls/QskAbstractTextInput.cpp
|
||||
controls/QskAnimator.cpp
|
||||
controls/QskAnimationHint.cpp
|
||||
controls/QskMainView.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,616 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) The authors
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskAbstractTextInput.h"
|
||||
#include "QskFontRole.h"
|
||||
#include "QskQuick.h"
|
||||
#include "QskEvent.h"
|
||||
#include "QskInternalMacros.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquicktextedit_p.h>
|
||||
#include <private/qquicktextinput_p.h>
|
||||
#include <private/qquicktextinput_p_p.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
#include <private/qeventpoint_p.h>
|
||||
#endif
|
||||
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
QSK_SUBCONTROL( QskAbstractTextInput, Text )
|
||||
|
||||
QSK_SYSTEM_STATE( QskAbstractTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskAbstractTextInput, Editing, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskAbstractTextInput, Selected, QskAspect::FirstSystemState << 3 )
|
||||
|
||||
static inline void qskUpdateInputMethodFont( const QskAbstractTextInput* input )
|
||||
{
|
||||
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
|
||||
qskUpdateInputMethod( input, queries );
|
||||
}
|
||||
|
||||
static inline QVariant qskInputMethodQuery(
|
||||
const QQuickItem* item, Qt::InputMethodQuery query, QVariant argument )
|
||||
{
|
||||
if ( auto input = qobject_cast< const QQuickTextInput* >( item ) )
|
||||
return input->inputMethodQuery( query, argument );
|
||||
|
||||
if ( auto edit = qobject_cast< const QQuickTextEdit* >( item ) )
|
||||
return edit->inputMethodQuery( query, argument );
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
static inline Qt::InputMethodHints qskInputMethodHints( const QQuickItem* item )
|
||||
{
|
||||
if ( auto input = qobject_cast< const QQuickTextInput* >( item ) )
|
||||
return input->inputMethodHints();
|
||||
|
||||
if ( auto edit = qobject_cast< const QQuickTextEdit* >( item ) )
|
||||
return edit->inputMethodHints();
|
||||
|
||||
return Qt::InputMethodHints();
|
||||
}
|
||||
|
||||
static inline void qskSetInputMethodHints(
|
||||
QQuickItem* item, Qt::InputMethodHints hints )
|
||||
{
|
||||
if ( auto input = qobject_cast< QQuickTextInput* >( item ) )
|
||||
input->setInputMethodHints( hints );
|
||||
else if ( auto edit = qobject_cast< QQuickTextEdit* >( item ) )
|
||||
edit->setInputMethodHints( hints );
|
||||
}
|
||||
|
||||
inline void qskSetAlignment( QQuickItem* item, Qt::Alignment alignment )
|
||||
{
|
||||
item->setProperty( "horizontalAlignment", int( alignment ) & 0x0f );
|
||||
item->setProperty( "verticalAlignment", int( alignment ) & 0xf0 );
|
||||
}
|
||||
|
||||
static inline void qskTranslateMouseEventPosition(
|
||||
QMouseEvent* mouseEvent, const QPointF& offset )
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
auto& point = mouseEvent->point(0);
|
||||
|
||||
QMutableEventPoint::setPosition(
|
||||
point, point.position() + offset );
|
||||
#else
|
||||
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void qskForwardEvent( QQuickItem* item, QEvent* event )
|
||||
{
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
const auto pos = item->position();
|
||||
|
||||
auto mouseEvent = static_cast< QMouseEvent* >( event );
|
||||
|
||||
/*
|
||||
As the event was sent for the parent item
|
||||
we have to translate the position into
|
||||
our coordinate system.
|
||||
*/
|
||||
qskTranslateMouseEventPosition( mouseEvent, -pos );
|
||||
|
||||
QMetaObject::invokeMethod( item, "handleEvent",
|
||||
Qt::DirectConnection, Q_ARG( QEvent*, event ) );
|
||||
|
||||
qskTranslateMouseEventPosition( mouseEvent, pos );
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
QMetaObject::invokeMethod( item, "handleEvent",
|
||||
Qt::DirectConnection, Q_ARG( QEvent*, event ) );
|
||||
}
|
||||
}
|
||||
|
||||
class QskAbstractTextInput::PrivateData
|
||||
{
|
||||
public:
|
||||
ActivationModes activationModes;
|
||||
};
|
||||
|
||||
QskAbstractTextInput::QskAbstractTextInput( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
|
||||
|
||||
setPolishOnResize( true );
|
||||
|
||||
setAcceptHoverEvents( true );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
setFlag( QQuickItem::ItemAcceptsInputMethod );
|
||||
}
|
||||
|
||||
QskAbstractTextInput::~QskAbstractTextInput()
|
||||
{
|
||||
}
|
||||
|
||||
QskAbstractTextInput::ActivationModes QskAbstractTextInput::activationModes() const
|
||||
{
|
||||
return m_data->activationModes;
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setActivationModes( ActivationModes modes )
|
||||
{
|
||||
if ( m_data->activationModes != modes )
|
||||
{
|
||||
m_data->activationModes = modes;
|
||||
Q_EMIT activationModesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::selectByMouse() const
|
||||
{
|
||||
return wrappedInput()->property( "selectByMouse" ).value< bool >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setSelectByMouse( bool on )
|
||||
{
|
||||
wrappedInput()->setProperty( "selectByMouse", on );
|
||||
}
|
||||
|
||||
QString QskAbstractTextInput::text() const
|
||||
{
|
||||
return wrappedInput()->property( "text" ).value< QString >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setText( const QString& text )
|
||||
{
|
||||
wrappedInput()->setProperty( "text", text );
|
||||
}
|
||||
|
||||
QString QskAbstractTextInput::preeditText() const
|
||||
{
|
||||
return wrappedInput()->property( "preeditText" ).value< QString >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::clear()
|
||||
{
|
||||
QMetaObject::invokeMethod( wrappedInput(), "clear" );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::selectAll()
|
||||
{
|
||||
QMetaObject::invokeMethod( wrappedInput(), "selectAll" );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::deselect()
|
||||
{
|
||||
QMetaObject::invokeMethod( wrappedInput(), "deselect" );
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::canUndo() const
|
||||
{
|
||||
return wrappedInput()->property( "canUndo" ).value< bool >();
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::canRedo() const
|
||||
{
|
||||
return wrappedInput()->property( "canRedo" ).value< bool >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setFontRole( const QskFontRole& role )
|
||||
{
|
||||
if ( setFontRoleHint( Text, role ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::resetFontRole()
|
||||
{
|
||||
if ( resetFontRoleHint( Text ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QskFontRole QskAbstractTextInput::fontRole() const
|
||||
{
|
||||
return fontRoleHint( Text );
|
||||
}
|
||||
|
||||
QFont QskAbstractTextInput::font() const
|
||||
{
|
||||
return effectiveFont( Text );
|
||||
}
|
||||
|
||||
QVariant QskAbstractTextInput::inputMethodQuery(
|
||||
Qt::InputMethodQuery property ) const
|
||||
{
|
||||
return inputMethodQuery( property, QVariant() );
|
||||
}
|
||||
|
||||
QVariant QskAbstractTextInput::inputMethodQuery(
|
||||
Qt::InputMethodQuery query, const QVariant& argument ) const
|
||||
{
|
||||
switch ( query )
|
||||
{
|
||||
case Qt::ImEnabled:
|
||||
{
|
||||
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
|
||||
}
|
||||
case Qt::ImFont:
|
||||
{
|
||||
return font();
|
||||
}
|
||||
case Qt::ImPreferredLanguage:
|
||||
{
|
||||
return locale();
|
||||
}
|
||||
case Qt::ImInputItemClipRectangle:
|
||||
case Qt::ImCursorRectangle:
|
||||
{
|
||||
QVariant v = qskInputMethodQuery( wrappedInput(), query, argument );
|
||||
#if 1
|
||||
if ( v.canConvert< QRectF >() )
|
||||
v.setValue( v.toRectF().translated( wrappedInput()->position() ) );
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return qskInputMethodQuery( wrappedInput(), query, argument );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt::InputMethodHints QskAbstractTextInput::inputMethodHints() const
|
||||
{
|
||||
return qskInputMethodHints( wrappedInput() );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setInputMethodHints( Qt::InputMethodHints hints )
|
||||
{
|
||||
if ( qskInputMethodHints( wrappedInput() ) != hints )
|
||||
{
|
||||
qskSetInputMethodHints( wrappedInput(), hints );
|
||||
qskUpdateInputMethod( this, Qt::ImHints );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::LocaleChange )
|
||||
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
|
||||
|
||||
if ( event->type() == QEvent::ShortcutOverride )
|
||||
{
|
||||
forwardEvent( event );
|
||||
return event->isAccepted();
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
forwardEvent( event );
|
||||
|
||||
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
forwardEvent( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
forwardEvent( event );
|
||||
|
||||
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::mouseDoubleClickEvent( QMouseEvent* event )
|
||||
{
|
||||
forwardEvent( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
if ( isEditing() )
|
||||
{
|
||||
switch ( event->key() )
|
||||
{
|
||||
case Qt::Key_Escape:
|
||||
{
|
||||
setEditing( false );
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
{
|
||||
const auto hints = inputMethodQuery( Qt::ImHints ).toInt();
|
||||
if ( !( hints & Qt::ImhMultiLine ) )
|
||||
{
|
||||
if ( acceptInput() )
|
||||
{
|
||||
QGuiApplication::inputMethod()->commit();
|
||||
setEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isEditing() )
|
||||
{
|
||||
forwardEvent( event );
|
||||
}
|
||||
else
|
||||
{
|
||||
// When returning from a virtual keyboard
|
||||
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( activationModes() & ActivationOnKey ) && !event->isAutoRepeat() )
|
||||
{
|
||||
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
|
||||
{
|
||||
setEditing( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::keyPressEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::keyReleaseEvent( QKeyEvent* event )
|
||||
{
|
||||
Inherited::keyReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::focusInEvent( QFocusEvent* event )
|
||||
{
|
||||
if ( activationModes() & ActivationOnFocus )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
break;
|
||||
|
||||
default:
|
||||
#if 1
|
||||
// auto selecting the complete text ???
|
||||
#endif
|
||||
setEditing( true );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusInEvent( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::focusOutEvent( QFocusEvent* event )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
deselect();
|
||||
setEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusOutEvent( event );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::inputMethodEvent( QInputMethodEvent* event )
|
||||
{
|
||||
const bool hadCursor = isCursorVisible();
|
||||
|
||||
forwardEvent( event );
|
||||
|
||||
if ( isCursorVisible() && !hadCursor )
|
||||
{
|
||||
/*
|
||||
The initial InputMethod events might be sent from the
|
||||
platform depending on focus. Unfortunately an
|
||||
empty dummy event ( = no attributes ) leads to showing
|
||||
the cursor.
|
||||
*/
|
||||
if ( isEditing() )
|
||||
setCursorVisible( false );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::isReadOnly() const
|
||||
{
|
||||
return wrappedInput()->property( "readOnly" ).value< bool >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setReadOnly( bool on )
|
||||
{
|
||||
if ( on == isReadOnly() )
|
||||
return;
|
||||
|
||||
#if 1
|
||||
// do we want to be able to restore the previous policy ?
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
#endif
|
||||
|
||||
auto input = wrappedInput();
|
||||
input->setProperty( "readOnly", on );
|
||||
|
||||
// we are killing user settings here ?
|
||||
input->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
|
||||
qskUpdateInputMethod( this, Qt::ImReadOnly );
|
||||
#else
|
||||
qskUpdateInputMethod( this, Qt::ImEnabled );
|
||||
#endif
|
||||
|
||||
setSkinStateFlag( ReadOnly, on );
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::isEditing() const
|
||||
{
|
||||
return hasSkinState( Editing );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setEditing( bool on )
|
||||
{
|
||||
if ( isReadOnly() || on == isEditing() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Editing, on );
|
||||
|
||||
auto input = wrappedInput();
|
||||
|
||||
if ( input->property( "cursorVisible" ).value< bool >() != on )
|
||||
{
|
||||
input->setProperty( "cursorVisible", on );
|
||||
|
||||
if ( auto textInput = qobject_cast< QQuickTextInput* >( input ) )
|
||||
{
|
||||
auto d = QQuickTextInputPrivate::get( textInput );
|
||||
d->setBlinkingCursorEnabled( on );
|
||||
|
||||
if ( !on )
|
||||
{
|
||||
if ( d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive() )
|
||||
d->updatePasswordEchoEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
input->polish();
|
||||
input->update();
|
||||
}
|
||||
|
||||
if ( !on && acceptInput() )
|
||||
QMetaObject::invokeMethod( input, "editingFinished" );
|
||||
|
||||
qskInputMethodSetVisible( this, on );
|
||||
Q_EMIT editingChanged( on );
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::acceptInput()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::overwriteMode() const
|
||||
{
|
||||
return wrappedInput()->property( "overwriteMode" ).value< bool >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setOverwriteMode( bool overwrite )
|
||||
{
|
||||
wrappedInput()->setProperty( "overwriteMode", overwrite );
|
||||
}
|
||||
|
||||
int QskAbstractTextInput::cursorPosition() const
|
||||
{
|
||||
return wrappedInput()->property( "cursorPosition" ).value< int >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setCursorPosition( int pos )
|
||||
{
|
||||
wrappedInput()->setProperty( "cursorPosition", pos );
|
||||
}
|
||||
|
||||
bool QskAbstractTextInput::isCursorVisible() const
|
||||
{
|
||||
return wrappedInput()->property( "cursorVisible" ).value< bool >();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setCursorVisible( bool on )
|
||||
{
|
||||
wrappedInput()->setProperty( "cursorVisible", on );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
|
||||
{
|
||||
wrappedInput()->setProperty( "wrapMode", static_cast< int >( wrapMode ) );
|
||||
}
|
||||
|
||||
QskTextOptions::WrapMode QskAbstractTextInput::wrapMode() const
|
||||
{
|
||||
const auto mode = wrappedInput()->property( "wrapMode" ).value< int >();
|
||||
return static_cast< QskTextOptions::WrapMode >( mode );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
if ( setAlignmentHint( Text, alignment ) )
|
||||
{
|
||||
qskSetAlignment( wrappedInput(), alignment );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::resetAlignment()
|
||||
{
|
||||
if ( resetAlignmentHint( Text ) )
|
||||
{
|
||||
qskSetAlignment( wrappedInput(), alignment() );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::Alignment QskAbstractTextInput::alignment() const
|
||||
{
|
||||
Qt::Alignment alignment = Qt::AlignLeft;
|
||||
if ( qobject_cast< const QQuickTextEdit* >( wrappedInput() ) )
|
||||
alignment |= Qt::AlignTop;
|
||||
else
|
||||
alignment |= Qt::AlignVCenter;
|
||||
|
||||
return alignmentHint( Text, alignment );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::updateLayout()
|
||||
{
|
||||
QMetaObject::invokeMethod( wrappedInput(), "updateMetrics" );
|
||||
qskSetItemGeometry( wrappedInput(), subControlRect( Text ) );
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::updateNode( QSGNode* node )
|
||||
{
|
||||
QMetaObject::invokeMethod( wrappedInput(), "updateColors" );
|
||||
Inherited::updateNode( node );
|
||||
}
|
||||
|
||||
const QQuickItem* QskAbstractTextInput::wrappedInput() const
|
||||
{
|
||||
auto that = const_cast< QskAbstractTextInput* >( this );
|
||||
return that->wrappedInput();
|
||||
}
|
||||
|
||||
void QskAbstractTextInput::forwardEvent( QEvent* event )
|
||||
{
|
||||
qskForwardEvent( wrappedInput(), event );
|
||||
}
|
||||
|
||||
#include "moc_QskAbstractTextInput.cpp"
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) The authors
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_ABSTRACT_TEXT_INPUT_H
|
||||
#define QSK_ABSTRACT_TEXT_INPUT_H
|
||||
|
||||
#include "QskControl.h"
|
||||
#include "QskTextOptions.h"
|
||||
|
||||
class QskFontRole;
|
||||
|
||||
class QSK_EXPORT QskAbstractTextInput : public QskControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString text READ text
|
||||
WRITE setText NOTIFY textChanged USER true )
|
||||
|
||||
Q_PROPERTY( QString preeditText READ preeditText
|
||||
NOTIFY preeditTextChanged )
|
||||
|
||||
Q_PROPERTY( bool editing READ isEditing
|
||||
WRITE setEditing NOTIFY editingChanged )
|
||||
|
||||
Q_PROPERTY( bool readOnly READ isReadOnly
|
||||
WRITE setReadOnly NOTIFY readOnlyChanged )
|
||||
|
||||
Q_PROPERTY( ActivationModes activationModes READ activationModes
|
||||
WRITE setActivationModes NOTIFY activationModesChanged )
|
||||
|
||||
Q_PROPERTY( QskFontRole fontRole READ fontRole
|
||||
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
|
||||
|
||||
Q_PROPERTY( QFont font READ font )
|
||||
|
||||
Q_PROPERTY( bool overwriteMode READ overwriteMode
|
||||
WRITE setOverwriteMode NOTIFY overwriteModeChanged )
|
||||
|
||||
Q_PROPERTY( bool cursorVisible READ isCursorVisible
|
||||
WRITE setCursorVisible NOTIFY cursorVisibleChanged )
|
||||
|
||||
Q_PROPERTY( int cursorPosition READ cursorPosition
|
||||
WRITE setCursorPosition NOTIFY cursorPositionChanged )
|
||||
|
||||
Q_PROPERTY( Qt::Alignment alignment READ alignment
|
||||
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
|
||||
|
||||
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
|
||||
WRITE setWrapMode NOTIFY wrapModeChanged )
|
||||
|
||||
Q_PROPERTY( bool selectByMouse READ selectByMouse
|
||||
WRITE setSelectByMouse NOTIFY selectByMouseChanged )
|
||||
|
||||
Q_PROPERTY( bool canUndo READ canUndo NOTIFY canUndoChanged )
|
||||
Q_PROPERTY( bool canRedo READ canRedo NOTIFY canRedoChanged )
|
||||
|
||||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Text )
|
||||
QSK_STATES( ReadOnly, Editing, Selected )
|
||||
|
||||
enum ActivationMode
|
||||
{
|
||||
NoActivation,
|
||||
|
||||
ActivationOnFocus = 1 << 0,
|
||||
ActivationOnMouse = 1 << 1,
|
||||
ActivationOnKey = 1 << 2,
|
||||
|
||||
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
|
||||
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
|
||||
};
|
||||
|
||||
Q_ENUM( ActivationMode )
|
||||
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
|
||||
|
||||
~QskAbstractTextInput() override;
|
||||
|
||||
QString text() const;
|
||||
QString preeditText() const;
|
||||
|
||||
bool isReadOnly() const;
|
||||
void setReadOnly( bool );
|
||||
|
||||
bool isEditing() const;
|
||||
|
||||
void setActivationModes( ActivationModes );
|
||||
ActivationModes activationModes() const;
|
||||
|
||||
void setSelectByMouse( bool );
|
||||
bool selectByMouse() const;
|
||||
|
||||
void setAlignment( Qt::Alignment );
|
||||
void resetAlignment();
|
||||
Qt::Alignment alignment() const;
|
||||
|
||||
void setWrapMode( QskTextOptions::WrapMode );
|
||||
QskTextOptions::WrapMode wrapMode() const;
|
||||
|
||||
void setFontRole( const QskFontRole& role );
|
||||
void resetFontRole();
|
||||
QskFontRole fontRole() const;
|
||||
|
||||
QFont font() const;
|
||||
|
||||
bool overwriteMode() const;
|
||||
void setOverwriteMode( bool );
|
||||
|
||||
bool isCursorVisible() const;
|
||||
void setCursorVisible( bool );
|
||||
|
||||
int cursorPosition() const;
|
||||
void setCursorPosition( int );
|
||||
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& ) const;
|
||||
|
||||
Qt::InputMethodHints inputMethodHints() const;
|
||||
void setInputMethodHints( Qt::InputMethodHints );
|
||||
|
||||
bool canUndo() const;
|
||||
bool canRedo() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setText( const QString& );
|
||||
void setEditing( bool );
|
||||
|
||||
void clear();
|
||||
void deselect();
|
||||
void selectAll();
|
||||
|
||||
Q_SIGNALS:
|
||||
void editingChanged( bool );
|
||||
void readOnlyChanged( bool );
|
||||
void activationModesChanged();
|
||||
void fontRoleChanged();
|
||||
void overwriteModeChanged( bool );
|
||||
void cursorPositionChanged( int );
|
||||
void cursorVisibleChanged( bool );
|
||||
void selectByMouseChanged( bool );
|
||||
|
||||
void wrapModeChanged( QskTextOptions::WrapMode );
|
||||
void alignmentChanged();
|
||||
|
||||
void textChanged( const QString& );
|
||||
void textEdited( const QString& );
|
||||
void displayTextChanged( const QString& );
|
||||
void preeditTextChanged( const QString& );
|
||||
|
||||
#if 1
|
||||
void canUndoChanged( bool );
|
||||
void canRedoChanged( bool );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
QskAbstractTextInput( QQuickItem* parent = nullptr );
|
||||
|
||||
virtual QQuickItem* wrappedInput() = 0;
|
||||
const QQuickItem* wrappedInput() const;
|
||||
|
||||
void forwardEvent( QEvent* );
|
||||
|
||||
bool event( QEvent* ) override;
|
||||
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseMoveEvent( QMouseEvent* ) override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent* ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void focusInEvent( QFocusEvent* ) override;
|
||||
void focusOutEvent( QFocusEvent* ) override;
|
||||
|
||||
void inputMethodEvent( QInputMethodEvent* ) override;
|
||||
|
||||
virtual bool acceptInput();
|
||||
|
||||
void updateLayout() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QskAbstractTextInput::ActivationModes )
|
||||
Q_DECLARE_METATYPE( QskAbstractTextInput::ActivationModes )
|
||||
|
||||
#endif
|
||||
|
|
@ -12,19 +12,9 @@
|
|||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquicktextedit_p.h>
|
||||
#include <private/qquicktextedit_p_p.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
#include <private/qeventpoint_p.h>
|
||||
#endif
|
||||
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
QSK_SUBCONTROL( QskTextEdit, TextPanel )
|
||||
QSK_SUBCONTROL( QskTextEdit, Text )
|
||||
|
||||
QSK_SYSTEM_STATE( QskTextEdit, ReadOnly, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskTextEdit, Editing, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskTextEdit, Error, QskAspect::FirstSystemState << 4 )
|
||||
|
||||
static inline void qskPropagateReadOnly( QskTextEdit* edit )
|
||||
{
|
||||
|
|
@ -34,19 +24,6 @@ static inline void qskPropagateReadOnly( QskTextEdit* edit )
|
|||
QCoreApplication::sendEvent( edit, &event );
|
||||
}
|
||||
|
||||
static inline void qskTranslateMouseEventPosition(
|
||||
QMouseEvent* mouseEvent, const QPointF& offset )
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
auto& point = mouseEvent->point( 0 );
|
||||
|
||||
QMutableEventPoint::setPosition(
|
||||
point, point.position() + offset );
|
||||
#else
|
||||
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void qskBindSignals(
|
||||
const QQuickTextEdit* wrappedEdit, QskTextEdit* edit )
|
||||
{
|
||||
|
|
@ -62,6 +39,9 @@ static inline void qskBindSignals(
|
|||
QObject::connect( wrappedEdit, &QQuickTextEdit::overwriteModeChanged,
|
||||
edit, &QskTextEdit::overwriteModeChanged );
|
||||
|
||||
QObject::connect( wrappedEdit, &QQuickTextEdit::cursorPositionChanged,
|
||||
edit, [ edit ] { Q_EMIT edit->cursorPositionChanged( edit->cursorPosition() ); } );
|
||||
|
||||
QObject::connect( wrappedEdit, &QQuickTextEdit::wrapModeChanged,
|
||||
edit, [ edit ] { Q_EMIT edit->wrapModeChanged( edit->wrapMode() ); } );
|
||||
|
||||
|
|
@ -92,57 +72,22 @@ namespace
|
|||
{
|
||||
class QuickTextEdit final : public QQuickTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QQuickTextEdit;
|
||||
|
||||
public:
|
||||
QuickTextEdit( QskTextEdit* );
|
||||
|
||||
void setEditing( bool on );
|
||||
|
||||
inline void setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
|
||||
setVAlign( ( VAlignment ) ( int( alignment ) & 0xf0 ) );
|
||||
}
|
||||
|
||||
void updateColors();
|
||||
void updateMetrics();
|
||||
|
||||
inline bool handleEvent( QEvent* event )
|
||||
{
|
||||
bool ok;
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
auto mouseEvent = static_cast< QMouseEvent* >( event );
|
||||
|
||||
/*
|
||||
As the event was sent for the parent item
|
||||
we have to translate the position into
|
||||
our coordinate system.
|
||||
*/
|
||||
qskTranslateMouseEventPosition( mouseEvent, -position() );
|
||||
ok = this->event( mouseEvent );
|
||||
qskTranslateMouseEventPosition( mouseEvent, position() );
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ok = this->event( event );
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
inline bool hasSelectedText() const
|
||||
{
|
||||
return !selectedText().isEmpty();
|
||||
}
|
||||
Q_INVOKABLE void updateColors();
|
||||
Q_INVOKABLE void updateMetrics();
|
||||
Q_INVOKABLE void handleEvent( QEvent* ev ) { event( ev ); }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
@ -192,19 +137,6 @@ namespace
|
|||
this, &QuickTextEdit::updateClip );
|
||||
}
|
||||
|
||||
void QuickTextEdit::setEditing( bool on )
|
||||
{
|
||||
auto d = QQuickTextEditPrivate::get( this );
|
||||
|
||||
if ( d->cursorVisible == on )
|
||||
return;
|
||||
|
||||
setCursorVisible( on );
|
||||
|
||||
polish();
|
||||
update();
|
||||
}
|
||||
|
||||
void QuickTextEdit::updateMetrics()
|
||||
{
|
||||
auto textEdit = static_cast< const QskTextEdit* >( parentItem() );
|
||||
|
|
@ -221,7 +153,7 @@ namespace
|
|||
|
||||
setColor( input->color( Q::Text ) );
|
||||
|
||||
const auto state = QskTextEditSkinlet::Selected;
|
||||
const auto state = QskTextEdit::Selected;
|
||||
|
||||
setSelectionColor( input->color( Q::TextPanel | state ) );
|
||||
setSelectedTextColor( input->color( Q::Text | state ) );
|
||||
|
|
@ -232,23 +164,12 @@ class QskTextEdit::PrivateData
|
|||
{
|
||||
public:
|
||||
QuickTextEdit* wrappedEdit;
|
||||
|
||||
ActivationModes activationModes;
|
||||
};
|
||||
|
||||
QskTextEdit::QskTextEdit( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
|
||||
|
||||
setPolishOnResize( true );
|
||||
|
||||
setAcceptHoverEvents( true );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
setFlag( QQuickItem::ItemAcceptsInputMethod );
|
||||
|
||||
/*
|
||||
QQuickTextEdit is a beast of almost 3.5k lines of code, we don't
|
||||
want to reimplement that - at least not now.
|
||||
|
|
@ -269,341 +190,6 @@ QskTextEdit::~QskTextEdit()
|
|||
{
|
||||
}
|
||||
|
||||
bool QskTextEdit::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::ShortcutOverride )
|
||||
{
|
||||
return m_data->wrappedEdit->handleEvent( event );
|
||||
}
|
||||
else if ( event->type() == QEvent::LocaleChange )
|
||||
{
|
||||
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
if ( isEditing() )
|
||||
{
|
||||
switch ( event->key() )
|
||||
{
|
||||
#if 1
|
||||
case Qt::Key_Escape:
|
||||
{
|
||||
setEditing( false );
|
||||
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( m_data->activationModes & ActivationOnKey ) && !event->isAutoRepeat() )
|
||||
{
|
||||
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
|
||||
{
|
||||
setEditing( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::keyPressEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::keyReleaseEvent( QKeyEvent* event )
|
||||
{
|
||||
Inherited::keyReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
|
||||
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskTextEdit::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
|
||||
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskTextEdit::mouseDoubleClickEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::inputMethodEvent( QInputMethodEvent* event )
|
||||
{
|
||||
m_data->wrappedEdit->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::focusInEvent( QFocusEvent* event )
|
||||
{
|
||||
if ( m_data->activationModes & ActivationOnFocus )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
break;
|
||||
|
||||
default:
|
||||
#if 1
|
||||
// auto selecting the complete text ???
|
||||
#endif
|
||||
setEditing( true );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusInEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::focusOutEvent( QFocusEvent* event )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
m_data->wrappedEdit->deselect();
|
||||
setEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusOutEvent( event );
|
||||
}
|
||||
|
||||
void QskTextEdit::updateLayout()
|
||||
{
|
||||
m_data->wrappedEdit->updateMetrics();
|
||||
qskSetItemGeometry( m_data->wrappedEdit, subControlRect( Text ) );
|
||||
}
|
||||
|
||||
void QskTextEdit::updateNode( QSGNode* node )
|
||||
{
|
||||
m_data->wrappedEdit->updateColors();
|
||||
Inherited::updateNode( node );
|
||||
}
|
||||
|
||||
QString QskTextEdit::text() const
|
||||
{
|
||||
return m_data->wrappedEdit->text();
|
||||
}
|
||||
|
||||
void QskTextEdit::setText( const QString& text )
|
||||
{
|
||||
m_data->wrappedEdit->setText( text );
|
||||
}
|
||||
|
||||
void QskTextEdit::clear()
|
||||
{
|
||||
m_data->wrappedEdit->clear();
|
||||
}
|
||||
|
||||
void QskTextEdit::selectAll()
|
||||
{
|
||||
m_data->wrappedEdit->selectAll();
|
||||
}
|
||||
|
||||
QskTextEdit::ActivationModes QskTextEdit::activationModes() const
|
||||
{
|
||||
return static_cast< QskTextEdit::ActivationModes >( m_data->activationModes );
|
||||
}
|
||||
|
||||
void QskTextEdit::setActivationModes( ActivationModes modes )
|
||||
{
|
||||
if ( static_cast< ActivationModes >( m_data->activationModes ) != modes )
|
||||
{
|
||||
m_data->activationModes = modes;
|
||||
Q_EMIT activationModesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qskUpdateInputMethodFont( const QskTextEdit* input )
|
||||
{
|
||||
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
|
||||
qskUpdateInputMethod( input, queries );
|
||||
}
|
||||
|
||||
void QskTextEdit::setFontRole( const QskFontRole& role )
|
||||
{
|
||||
if ( setFontRoleHint( Text, role ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskTextEdit::resetFontRole()
|
||||
{
|
||||
if ( resetFontRoleHint( Text ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QskFontRole QskTextEdit::fontRole() const
|
||||
{
|
||||
return fontRoleHint( Text );
|
||||
}
|
||||
|
||||
void QskTextEdit::setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
if ( setAlignmentHint( Text, alignment ) )
|
||||
{
|
||||
m_data->wrappedEdit->setAlignment( alignment );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskTextEdit::resetAlignment()
|
||||
{
|
||||
if ( resetAlignmentHint( Text ) )
|
||||
{
|
||||
m_data->wrappedEdit->setAlignment( alignment() );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::Alignment QskTextEdit::alignment() const
|
||||
{
|
||||
return alignmentHint( Text, Qt::AlignLeft | Qt::AlignTop );
|
||||
}
|
||||
|
||||
void QskTextEdit::setWrapMode( QskTextOptions::WrapMode wrapMode )
|
||||
{
|
||||
m_data->wrappedEdit->setWrapMode(
|
||||
static_cast< QQuickTextEdit::WrapMode >( wrapMode ) );
|
||||
}
|
||||
|
||||
QskTextOptions::WrapMode QskTextEdit::wrapMode() const
|
||||
{
|
||||
return static_cast< QskTextOptions::WrapMode >(
|
||||
m_data->wrappedEdit->wrapMode() );
|
||||
}
|
||||
|
||||
void QskTextEdit::setSelectByMouse( bool on )
|
||||
{
|
||||
m_data->wrappedEdit->setSelectByMouse( on );
|
||||
}
|
||||
|
||||
bool QskTextEdit::selectByMouse() const
|
||||
{
|
||||
return m_data->wrappedEdit->selectByMouse();
|
||||
}
|
||||
|
||||
QFont QskTextEdit::font() const
|
||||
{
|
||||
return effectiveFont( QskTextEdit::Text );
|
||||
}
|
||||
|
||||
bool QskTextEdit::isReadOnly() const
|
||||
{
|
||||
return m_data->wrappedEdit->isReadOnly();
|
||||
}
|
||||
|
||||
void QskTextEdit::setReadOnly( bool on )
|
||||
{
|
||||
auto edit = m_data->wrappedEdit;
|
||||
|
||||
if ( edit->isReadOnly() == on )
|
||||
return;
|
||||
|
||||
#if 1
|
||||
// do we want to be able to restore the previous policy ?
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
#endif
|
||||
|
||||
edit->setReadOnly( on );
|
||||
|
||||
// we are killing user settings here ?
|
||||
edit->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
|
||||
qskUpdateInputMethod( this, Qt::ImEnabled );
|
||||
|
||||
setSkinStateFlag( ReadOnly, on );
|
||||
}
|
||||
|
||||
void QskTextEdit::setEditing( bool on )
|
||||
{
|
||||
if ( isReadOnly() || on == isEditing() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Editing, on );
|
||||
m_data->wrappedEdit->setEditing( on );
|
||||
|
||||
if ( on )
|
||||
{
|
||||
#if 0
|
||||
updateInputMethod( Qt::ImCursorRectangle | Qt::ImAnchorRectangle );
|
||||
QGuiApplication::inputMethod()->inputDirection
|
||||
#endif
|
||||
qskInputMethodSetVisible( this, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT m_data->wrappedEdit->editingFinished();
|
||||
|
||||
#if 0
|
||||
inputMethod->reset();
|
||||
#endif
|
||||
qskInputMethodSetVisible( this, false );
|
||||
}
|
||||
|
||||
Q_EMIT editingChanged( on );
|
||||
}
|
||||
|
||||
bool QskTextEdit::isEditing() const
|
||||
{
|
||||
return hasSkinState( Editing );
|
||||
}
|
||||
|
||||
int QskTextEdit::cursorPosition() const
|
||||
{
|
||||
return m_data->wrappedEdit->cursorPosition();
|
||||
}
|
||||
|
||||
void QskTextEdit::setCursorPosition( int pos )
|
||||
{
|
||||
m_data->wrappedEdit->setCursorPosition( pos );
|
||||
}
|
||||
|
||||
QString QskTextEdit::preeditText() const
|
||||
{
|
||||
return m_data->wrappedEdit->preeditText();
|
||||
}
|
||||
|
||||
bool QskTextEdit::overwriteMode() const
|
||||
{
|
||||
return m_data->wrappedEdit->overwriteMode();
|
||||
}
|
||||
|
||||
void QskTextEdit::setOverwriteMode( bool overwrite )
|
||||
{
|
||||
m_data->wrappedEdit->setOverwriteMode( overwrite );
|
||||
}
|
||||
|
||||
void QskTextEdit::setTextFormat( QskTextOptions::TextFormat textFormat )
|
||||
{
|
||||
m_data->wrappedEdit->setTextFormat(
|
||||
|
|
@ -621,70 +207,6 @@ int QskTextEdit::lineCount() const
|
|||
return m_data->wrappedEdit->lineCount();
|
||||
}
|
||||
|
||||
QVariant QskTextEdit::inputMethodQuery(
|
||||
Qt::InputMethodQuery property ) const
|
||||
{
|
||||
return inputMethodQuery( property, QVariant() );
|
||||
}
|
||||
|
||||
QVariant QskTextEdit::inputMethodQuery(
|
||||
Qt::InputMethodQuery query, const QVariant& argument ) const
|
||||
{
|
||||
switch ( query )
|
||||
{
|
||||
case Qt::ImEnabled:
|
||||
{
|
||||
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
|
||||
}
|
||||
case Qt::ImFont:
|
||||
{
|
||||
return font();
|
||||
}
|
||||
case Qt::ImPreferredLanguage:
|
||||
{
|
||||
return locale();
|
||||
}
|
||||
case Qt::ImInputItemClipRectangle:
|
||||
case Qt::ImCursorRectangle:
|
||||
{
|
||||
QVariant v = m_data->wrappedEdit->inputMethodQuery( query, argument );
|
||||
#if 1
|
||||
if ( v.canConvert< QRectF >() )
|
||||
v.setValue( v.toRectF().translated( m_data->wrappedEdit->position() ) );
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return m_data->wrappedEdit->inputMethodQuery( query, argument );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QskTextEdit::canUndo() const
|
||||
{
|
||||
return m_data->wrappedEdit->canUndo();
|
||||
}
|
||||
|
||||
bool QskTextEdit::canRedo() const
|
||||
{
|
||||
return m_data->wrappedEdit->canRedo();
|
||||
}
|
||||
|
||||
Qt::InputMethodHints QskTextEdit::inputMethodHints() const
|
||||
{
|
||||
return m_data->wrappedEdit->inputMethodHints();
|
||||
}
|
||||
|
||||
void QskTextEdit::setInputMethodHints( Qt::InputMethodHints hints )
|
||||
{
|
||||
if ( m_data->wrappedEdit->inputMethodHints() != hints )
|
||||
{
|
||||
m_data->wrappedEdit->setInputMethodHints( hints );
|
||||
qskUpdateInputMethod( this, Qt::ImHints );
|
||||
}
|
||||
}
|
||||
|
||||
int QskTextEdit::tabStopDistance() const
|
||||
{
|
||||
return m_data->wrappedEdit->tabStopDistance();
|
||||
|
|
@ -741,4 +263,10 @@ void QskTextEdit::setupFrom( const QQuickItem* item )
|
|||
}
|
||||
}
|
||||
|
||||
QQuickItem* QskTextEdit::wrappedInput()
|
||||
{
|
||||
return m_data->wrappedEdit;
|
||||
}
|
||||
|
||||
#include "QskTextEdit.moc"
|
||||
#include "moc_QskTextEdit.cpp"
|
||||
|
|
|
|||
|
|
@ -6,185 +6,53 @@
|
|||
#ifndef QSK_TEXT_EDIT_H
|
||||
#define QSK_TEXT_EDIT_H
|
||||
|
||||
#include "QskControl.h"
|
||||
#include "QskAbstractTextInput.h"
|
||||
#include "QskTextOptions.h"
|
||||
|
||||
class QValidator;
|
||||
class QskFontRole;
|
||||
|
||||
class QSK_EXPORT QskTextEdit : public QskControl
|
||||
class QSK_EXPORT QskTextEdit : public QskAbstractTextInput
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString text READ text
|
||||
WRITE setText NOTIFY textChanged USER true )
|
||||
|
||||
Q_PROPERTY( QskFontRole fontRole READ fontRole
|
||||
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
|
||||
|
||||
Q_PROPERTY( QFont font READ font )
|
||||
|
||||
Q_PROPERTY( Qt::Alignment alignment READ alignment
|
||||
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
|
||||
|
||||
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
|
||||
WRITE setWrapMode NOTIFY wrapModeChanged )
|
||||
|
||||
Q_PROPERTY( int lineCount READ lineCount NOTIFY lineCountChanged )
|
||||
|
||||
Q_PROPERTY( QskTextOptions::TextFormat textFormat READ textFormat
|
||||
WRITE setTextFormat NOTIFY textFormatChanged )
|
||||
|
||||
Q_PROPERTY( ActivationModes activationModes READ activationModes
|
||||
WRITE setActivationModes NOTIFY activationModesChanged )
|
||||
|
||||
Q_PROPERTY( bool selectByMouse READ selectByMouse
|
||||
WRITE setSelectByMouse NOTIFY selectByMouseChanged )
|
||||
|
||||
Q_PROPERTY( bool editing READ isEditing
|
||||
WRITE setEditing NOTIFY editingChanged )
|
||||
|
||||
Q_PROPERTY( qreal tabStopDistance READ tabStopDistance
|
||||
WRITE setTabStopDistance NOTIFY tabStopDistanceChanged )
|
||||
|
||||
using Inherited = QskControl;
|
||||
using Inherited = QskAbstractTextInput;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( TextPanel, Text )
|
||||
QSK_STATES( ReadOnly, Editing, Error )
|
||||
|
||||
enum ActivationMode
|
||||
{
|
||||
NoActivation,
|
||||
|
||||
ActivationOnFocus = 1 << 0,
|
||||
ActivationOnMouse = 1 << 1,
|
||||
ActivationOnKey = 1 << 2,
|
||||
|
||||
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
|
||||
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
|
||||
};
|
||||
|
||||
Q_ENUM( ActivationMode )
|
||||
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
|
||||
QSK_SUBCONTROLS( TextPanel )
|
||||
|
||||
QskTextEdit( QQuickItem* parent = nullptr );
|
||||
|
||||
~QskTextEdit() override;
|
||||
|
||||
void setupFrom( const QQuickItem* );
|
||||
|
||||
QString text() const;
|
||||
|
||||
void setFontRole( const QskFontRole& role );
|
||||
void resetFontRole();
|
||||
QskFontRole fontRole() const;
|
||||
|
||||
void setAlignment( Qt::Alignment );
|
||||
void resetAlignment();
|
||||
Qt::Alignment alignment() const;
|
||||
|
||||
void setWrapMode( QskTextOptions::WrapMode );
|
||||
QskTextOptions::WrapMode wrapMode() const;
|
||||
|
||||
void setTextFormat( QskTextOptions::TextFormat );
|
||||
QskTextOptions::TextFormat textFormat() const;
|
||||
|
||||
int lineCount() const;
|
||||
|
||||
void setActivationModes( ActivationModes );
|
||||
ActivationModes activationModes() const;
|
||||
|
||||
void setSelectByMouse( bool );
|
||||
bool selectByMouse() const;
|
||||
|
||||
bool isEditing() const;
|
||||
|
||||
QFont font() const;
|
||||
|
||||
bool isReadOnly() const;
|
||||
void setReadOnly( bool );
|
||||
|
||||
int cursorPosition() const;
|
||||
void setCursorPosition( int );
|
||||
|
||||
QString preeditText() const;
|
||||
|
||||
bool overwriteMode() const;
|
||||
void setOverwriteMode( bool );
|
||||
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& argument ) const;
|
||||
|
||||
bool canUndo() const;
|
||||
bool canRedo() const;
|
||||
|
||||
Qt::InputMethodHints inputMethodHints() const;
|
||||
void setInputMethodHints( Qt::InputMethodHints );
|
||||
|
||||
int tabStopDistance() const;
|
||||
void setTabStopDistance( qreal );
|
||||
|
||||
public Q_SLOTS:
|
||||
void clear();
|
||||
void selectAll();
|
||||
void setText( const QString& );
|
||||
void setEditing( bool );
|
||||
|
||||
Q_SIGNALS:
|
||||
void textChanged( const QString& );
|
||||
void preeditTextChanged( const QString& );
|
||||
|
||||
void editingChanged( bool );
|
||||
|
||||
void activationModesChanged();
|
||||
void readOnlyChanged( bool );
|
||||
void panelChanged( bool );
|
||||
|
||||
void displayTextChanged( const QString& );
|
||||
|
||||
void textEdited( const QString& );
|
||||
void placeholderTextChanged( const QString& );
|
||||
|
||||
void fontRoleChanged();
|
||||
void alignmentChanged();
|
||||
void wrapModeChanged( QskTextOptions::WrapMode );
|
||||
|
||||
void lineCountChanged( int );
|
||||
|
||||
void selectByMouseChanged( bool );
|
||||
|
||||
void textFormatChanged( QskTextOptions::TextFormat );
|
||||
|
||||
void overwriteModeChanged( bool );
|
||||
|
||||
void tabStopDistanceChanged( qreal );
|
||||
|
||||
protected:
|
||||
bool event( QEvent* ) override;
|
||||
|
||||
void inputMethodEvent( QInputMethodEvent* ) override;
|
||||
|
||||
void focusInEvent( QFocusEvent* ) override;
|
||||
void focusOutEvent( QFocusEvent* ) override;
|
||||
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseMoveEvent( QMouseEvent* ) override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent* ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void updateLayout() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
QQuickItem* wrappedInput() override final;
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextEdit::ActivationModes )
|
||||
Q_DECLARE_METATYPE( QskTextEdit::ActivationModes )
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
using Q = QskTextEdit;
|
||||
|
||||
QSK_SYSTEM_STATE( QskTextEditSkinlet, Selected, QskAspect::FirstSystemState << 3 )
|
||||
|
||||
QskTextEditSkinlet::QskTextEditSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ class QSK_EXPORT QskTextEditSkinlet : public QskSkinlet
|
|||
using Inherited = QskSkinlet;
|
||||
|
||||
public:
|
||||
QSK_STATES( Selected )
|
||||
|
||||
enum NodeRole : quint8
|
||||
{
|
||||
TextPanelRole,
|
||||
|
|
|
|||
|
|
@ -13,17 +13,10 @@ QSK_QT_PRIVATE_BEGIN
|
|||
#include <private/qquicktextinput_p.h>
|
||||
#include <private/qquicktextinput_p_p.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
#include <private/qeventpoint_p.h>
|
||||
#endif
|
||||
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
QSK_SUBCONTROL( QskTextInput, Text )
|
||||
QSK_SUBCONTROL( QskTextInput, TextPanel )
|
||||
|
||||
QSK_SYSTEM_STATE( QskTextInput, ReadOnly, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskTextInput, Editing, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskTextInput, Error, QskAspect::FirstSystemState << 4 )
|
||||
|
||||
static inline void qskPropagateReadOnly( QskTextInput* input )
|
||||
|
|
@ -34,19 +27,6 @@ static inline void qskPropagateReadOnly( QskTextInput* input )
|
|||
QCoreApplication::sendEvent( input, &event );
|
||||
}
|
||||
|
||||
static inline void qskTranslateMouseEventPosition(
|
||||
QMouseEvent* mouseEvent, const QPointF& offset )
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
auto& point = mouseEvent->point(0);
|
||||
|
||||
QMutableEventPoint::setPosition(
|
||||
point, point.position() + offset );
|
||||
#else
|
||||
mouseEvent->setLocalPos( mouseEvent->localPos() + offset );
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void qskBindSignals(
|
||||
const QQuickTextInput* wrappedInput, QskTextInput* input )
|
||||
{
|
||||
|
|
@ -71,6 +51,9 @@ static inline void qskBindSignals(
|
|||
QObject::connect( wrappedInput, &QQuickTextInput::overwriteModeChanged,
|
||||
input, &QskTextInput::overwriteModeChanged );
|
||||
|
||||
QObject::connect( wrappedInput, &QQuickTextInput::cursorPositionChanged,
|
||||
input, [ input ] { Q_EMIT input->cursorPositionChanged( input->cursorPosition() ); } );
|
||||
|
||||
QObject::connect( wrappedInput, &QQuickTextInput::maximumLengthChanged,
|
||||
input, &QskTextInput::maximumLengthChanged );
|
||||
|
||||
|
|
@ -97,13 +80,13 @@ namespace
|
|||
{
|
||||
class QuickTextInput final : public QQuickTextInput
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QQuickTextInput;
|
||||
|
||||
public:
|
||||
QuickTextInput( QskTextInput* );
|
||||
|
||||
void setEditing( bool on );
|
||||
|
||||
inline void setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
setHAlign( ( HAlignment ) ( int( alignment ) & 0x0f ) );
|
||||
|
|
@ -115,60 +98,9 @@ namespace
|
|||
return QQuickTextInputPrivate::get( this )->fixup();
|
||||
}
|
||||
|
||||
void updateColors();
|
||||
void updateMetrics();
|
||||
|
||||
inline bool handleEvent( QEvent* event )
|
||||
{
|
||||
bool ok;
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
auto mouseEvent = static_cast< QMouseEvent* >( event );
|
||||
|
||||
/*
|
||||
As the event was sent for the parent item
|
||||
we have to translate the position into
|
||||
our coordinate system.
|
||||
*/
|
||||
qskTranslateMouseEventPosition( mouseEvent, -position() );
|
||||
ok = this->event( mouseEvent );
|
||||
qskTranslateMouseEventPosition( mouseEvent, position() );
|
||||
|
||||
break;
|
||||
}
|
||||
case QEvent::InputMethod:
|
||||
{
|
||||
const bool hadCursor = isCursorVisible();
|
||||
|
||||
ok = this->event( event );
|
||||
|
||||
if ( isCursorVisible() && !hadCursor )
|
||||
{
|
||||
/*
|
||||
The initial InputMethod events might be sent from the
|
||||
platform depending on focus. Unfortunately an
|
||||
empty dummy event ( = no attributes ) leads to showing
|
||||
the cursor.
|
||||
*/
|
||||
auto input = static_cast< const QskTextInput* >( parentItem() );
|
||||
if ( !input->isEditing() )
|
||||
setCursorVisible( false );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ok = this->event( event );
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
Q_INVOKABLE void updateColors();
|
||||
Q_INVOKABLE void updateMetrics();
|
||||
Q_INVOKABLE void handleEvent( QEvent* );
|
||||
|
||||
protected:
|
||||
|
||||
|
|
@ -218,25 +150,6 @@ namespace
|
|||
this, &QuickTextInput::updateClip );
|
||||
}
|
||||
|
||||
void QuickTextInput::setEditing( bool on )
|
||||
{
|
||||
auto d = QQuickTextInputPrivate::get( this );
|
||||
|
||||
if ( d->cursorVisible == on )
|
||||
return;
|
||||
|
||||
setCursorVisible( on );
|
||||
d->setBlinkingCursorEnabled( on );
|
||||
|
||||
if ( !on )
|
||||
{
|
||||
if ( d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive() )
|
||||
d->updatePasswordEchoEditing( false );
|
||||
}
|
||||
|
||||
polish();
|
||||
update();
|
||||
}
|
||||
|
||||
void QuickTextInput::updateMetrics()
|
||||
{
|
||||
|
|
@ -254,34 +167,29 @@ namespace
|
|||
|
||||
setColor( input->color( Q::Text ) );
|
||||
|
||||
const auto state = QskTextInputSkinlet::Selected;
|
||||
const auto state = QskTextInput::Selected;
|
||||
|
||||
setSelectionColor( input->color( Q::TextPanel | state ) );
|
||||
setSelectedTextColor( input->color( Q::Text | state ) );
|
||||
}
|
||||
|
||||
void QuickTextInput::handleEvent( QEvent* ev )
|
||||
{
|
||||
event( ev );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class QskTextInput::PrivateData
|
||||
{
|
||||
public:
|
||||
QuickTextInput* wrappedInput;
|
||||
|
||||
ActivationModes activationModes;
|
||||
};
|
||||
|
||||
QskTextInput::QskTextInput( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
m_data->activationModes = ActivationOnMouse | ActivationOnKey;
|
||||
|
||||
setPolishOnResize( true );
|
||||
|
||||
setAcceptHoverEvents( true );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
setFlag( QQuickItem::ItemAcceptsInputMethod );
|
||||
|
||||
/*
|
||||
QQuickTextInput is a beast of almost 5k lines of code, we don't
|
||||
want to reimplement that - at least not now.
|
||||
|
|
@ -302,355 +210,11 @@ QskTextInput::~QskTextInput()
|
|||
{
|
||||
}
|
||||
|
||||
bool QskTextInput::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::ShortcutOverride )
|
||||
{
|
||||
return m_data->wrappedInput->handleEvent( event );
|
||||
}
|
||||
else if ( event->type() == QEvent::LocaleChange )
|
||||
{
|
||||
qskUpdateInputMethod( this, Qt::ImPreferredLanguage );
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskTextInput::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
if ( isEditing() )
|
||||
{
|
||||
switch ( event->key() )
|
||||
{
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
{
|
||||
const auto hints = inputMethodQuery( Qt::ImHints ).toInt();
|
||||
if ( !( hints & Qt::ImhMultiLine ) )
|
||||
{
|
||||
if ( hasAcceptableInput() || fixup() )
|
||||
{
|
||||
QGuiApplication::inputMethod()->commit();
|
||||
setEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#if 1
|
||||
case Qt::Key_Escape:
|
||||
{
|
||||
setEditing( false );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( isEditing() )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
}
|
||||
else
|
||||
{
|
||||
// When returning from a virtual keyboard
|
||||
qskForceActiveFocus( this, Qt::PopupFocusReason );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( m_data->activationModes & ActivationOnKey ) && !event->isAutoRepeat() )
|
||||
{
|
||||
if ( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
|
||||
{
|
||||
setEditing( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::keyPressEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::keyReleaseEvent( QKeyEvent* event )
|
||||
{
|
||||
Inherited::keyReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
|
||||
if ( !isReadOnly() && !qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskTextInput::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
|
||||
if ( !isReadOnly() && qGuiApp->styleHints()->setFocusOnTouchRelease() )
|
||||
setEditing( true );
|
||||
}
|
||||
|
||||
void QskTextInput::mouseDoubleClickEvent( QMouseEvent* event )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::inputMethodEvent( QInputMethodEvent* event )
|
||||
{
|
||||
m_data->wrappedInput->handleEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::focusInEvent( QFocusEvent* event )
|
||||
{
|
||||
if ( m_data->activationModes & ActivationOnFocus )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
break;
|
||||
|
||||
default:
|
||||
#if 1
|
||||
// auto selecting the complete text ???
|
||||
#endif
|
||||
setEditing( true );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusInEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::focusOutEvent( QFocusEvent* event )
|
||||
{
|
||||
switch ( event->reason() )
|
||||
{
|
||||
case Qt::ActiveWindowFocusReason:
|
||||
case Qt::PopupFocusReason:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
m_data->wrappedInput->deselect();
|
||||
setEditing( false );
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::focusOutEvent( event );
|
||||
}
|
||||
|
||||
void QskTextInput::updateLayout()
|
||||
{
|
||||
m_data->wrappedInput->updateMetrics();
|
||||
qskSetItemGeometry( m_data->wrappedInput, subControlRect( Text ) );
|
||||
}
|
||||
|
||||
void QskTextInput::updateNode( QSGNode* node )
|
||||
{
|
||||
m_data->wrappedInput->updateColors();
|
||||
Inherited::updateNode( node );
|
||||
}
|
||||
|
||||
QString QskTextInput::text() const
|
||||
{
|
||||
return m_data->wrappedInput->text();
|
||||
}
|
||||
|
||||
void QskTextInput::setText( const QString& text )
|
||||
{
|
||||
m_data->wrappedInput->setText( text );
|
||||
}
|
||||
|
||||
void QskTextInput::clear()
|
||||
{
|
||||
m_data->wrappedInput->clear();
|
||||
}
|
||||
|
||||
void QskTextInput::selectAll()
|
||||
{
|
||||
m_data->wrappedInput->selectAll();
|
||||
}
|
||||
|
||||
QskTextInput::ActivationModes QskTextInput::activationModes() const
|
||||
{
|
||||
return static_cast< QskTextInput::ActivationModes >( m_data->activationModes );
|
||||
}
|
||||
|
||||
void QskTextInput::setActivationModes( ActivationModes modes )
|
||||
{
|
||||
if ( static_cast< ActivationModes >( m_data->activationModes ) != modes )
|
||||
{
|
||||
m_data->activationModes = modes;
|
||||
Q_EMIT activationModesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qskUpdateInputMethodFont( const QskTextInput* input )
|
||||
{
|
||||
const auto queries = Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle;
|
||||
qskUpdateInputMethod( input, queries );
|
||||
}
|
||||
|
||||
void QskTextInput::setFontRole( const QskFontRole& role )
|
||||
{
|
||||
if ( setFontRoleHint( Text, role ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskTextInput::resetFontRole()
|
||||
{
|
||||
if ( resetFontRoleHint( Text ) )
|
||||
{
|
||||
qskUpdateInputMethodFont( this );
|
||||
Q_EMIT fontRoleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QskFontRole QskTextInput::fontRole() const
|
||||
{
|
||||
return fontRoleHint( Text );
|
||||
}
|
||||
|
||||
void QskTextInput::setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
if ( setAlignmentHint( Text, alignment ) )
|
||||
{
|
||||
m_data->wrappedInput->setAlignment( alignment );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskTextInput::resetAlignment()
|
||||
{
|
||||
if ( resetAlignmentHint( Text ) )
|
||||
{
|
||||
m_data->wrappedInput->setAlignment( alignment() );
|
||||
Q_EMIT alignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::Alignment QskTextInput::alignment() const
|
||||
{
|
||||
return alignmentHint( Text, Qt::AlignLeft | Qt::AlignTop );
|
||||
}
|
||||
|
||||
void QskTextInput::setWrapMode( QskTextOptions::WrapMode wrapMode )
|
||||
{
|
||||
m_data->wrappedInput->setWrapMode(
|
||||
static_cast< QQuickTextInput::WrapMode >( wrapMode ) );
|
||||
}
|
||||
|
||||
QskTextOptions::WrapMode QskTextInput::wrapMode() const
|
||||
{
|
||||
return static_cast< QskTextOptions::WrapMode >(
|
||||
m_data->wrappedInput->wrapMode() );
|
||||
}
|
||||
|
||||
void QskTextInput::setSelectByMouse( bool on )
|
||||
{
|
||||
m_data->wrappedInput->setSelectByMouse( on );
|
||||
}
|
||||
|
||||
bool QskTextInput::selectByMouse() const
|
||||
{
|
||||
return m_data->wrappedInput->selectByMouse();
|
||||
}
|
||||
|
||||
QFont QskTextInput::font() const
|
||||
{
|
||||
return effectiveFont( QskTextInput::Text );
|
||||
}
|
||||
|
||||
bool QskTextInput::isReadOnly() const
|
||||
{
|
||||
return m_data->wrappedInput->isReadOnly();
|
||||
}
|
||||
|
||||
void QskTextInput::setReadOnly( bool on )
|
||||
{
|
||||
auto input = m_data->wrappedInput;
|
||||
|
||||
if ( input->isReadOnly() == on )
|
||||
return;
|
||||
|
||||
#if 1
|
||||
// do we want to be able to restore the previous policy ?
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
#endif
|
||||
|
||||
input->setReadOnly( on );
|
||||
|
||||
// we are killing user settings here ?
|
||||
input->setFlag( QQuickItem::ItemAcceptsInputMethod, !on );
|
||||
qskUpdateInputMethod( this, Qt::ImEnabled );
|
||||
#if 0
|
||||
qskUpdateInputMethod( this, Qt::ImReadOnly ); // since 6.2
|
||||
#endif
|
||||
|
||||
setSkinStateFlag( ReadOnly, on );
|
||||
}
|
||||
|
||||
void QskTextInput::setEditing( bool on )
|
||||
{
|
||||
if ( isReadOnly() || on == isEditing() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Editing, on );
|
||||
m_data->wrappedInput->setEditing( on );
|
||||
|
||||
if ( on )
|
||||
{
|
||||
#if 0
|
||||
updateInputMethod( Qt::ImCursorRectangle | Qt::ImAnchorRectangle );
|
||||
QGuiApplication::inputMethod()->inputDirection
|
||||
#endif
|
||||
qskInputMethodSetVisible( this, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( hasAcceptableInput() || fixup() )
|
||||
Q_EMIT m_data->wrappedInput->editingFinished();
|
||||
|
||||
#if 0
|
||||
inputMethod->reset();
|
||||
#endif
|
||||
qskInputMethodSetVisible( this, false );
|
||||
}
|
||||
|
||||
Q_EMIT editingChanged( on );
|
||||
}
|
||||
|
||||
bool QskTextInput::isEditing() const
|
||||
{
|
||||
return hasSkinState( Editing );
|
||||
}
|
||||
|
||||
void QskTextInput::ensureVisible( int position )
|
||||
{
|
||||
m_data->wrappedInput->ensureVisible( position );
|
||||
}
|
||||
|
||||
int QskTextInput::cursorPosition() const
|
||||
{
|
||||
return m_data->wrappedInput->cursorPosition();
|
||||
}
|
||||
|
||||
void QskTextInput::setCursorPosition( int pos )
|
||||
{
|
||||
m_data->wrappedInput->setCursorPosition( pos );
|
||||
}
|
||||
|
||||
int QskTextInput::maxLength() const
|
||||
{
|
||||
return m_data->wrappedInput->maxLength();
|
||||
|
|
@ -734,22 +298,6 @@ QString QskTextInput::displayText() const
|
|||
return m_data->wrappedInput->displayText();
|
||||
}
|
||||
|
||||
QString QskTextInput::preeditText() const
|
||||
{
|
||||
const auto d = QQuickTextInputPrivate::get( m_data->wrappedInput );
|
||||
return d->m_textLayout.preeditAreaText();
|
||||
}
|
||||
|
||||
bool QskTextInput::overwriteMode() const
|
||||
{
|
||||
return m_data->wrappedInput->overwriteMode();
|
||||
}
|
||||
|
||||
void QskTextInput::setOverwriteMode( bool overwrite )
|
||||
{
|
||||
m_data->wrappedInput->setOverwriteMode( overwrite );
|
||||
}
|
||||
|
||||
bool QskTextInput::hasAcceptableInput() const
|
||||
{
|
||||
return m_data->wrappedInput->hasAcceptableInput();
|
||||
|
|
@ -760,58 +308,9 @@ bool QskTextInput::fixup()
|
|||
return m_data->wrappedInput->fixup();
|
||||
}
|
||||
|
||||
QVariant QskTextInput::inputMethodQuery(
|
||||
Qt::InputMethodQuery property ) const
|
||||
bool QskTextInput::acceptInput()
|
||||
{
|
||||
return inputMethodQuery( property, QVariant() );
|
||||
}
|
||||
|
||||
QVariant QskTextInput::inputMethodQuery(
|
||||
Qt::InputMethodQuery query, const QVariant& argument ) const
|
||||
{
|
||||
switch ( query )
|
||||
{
|
||||
case Qt::ImEnabled:
|
||||
{
|
||||
return QVariant( ( bool ) ( flags() & ItemAcceptsInputMethod ) );
|
||||
}
|
||||
case Qt::ImFont:
|
||||
{
|
||||
return font();
|
||||
}
|
||||
case Qt::ImPreferredLanguage:
|
||||
{
|
||||
return locale();
|
||||
}
|
||||
case Qt::ImInputItemClipRectangle:
|
||||
case Qt::ImCursorRectangle:
|
||||
{
|
||||
QVariant v = m_data->wrappedInput->inputMethodQuery( query, argument );
|
||||
#if 1
|
||||
if ( v.canConvert< QRectF >() )
|
||||
v.setValue( v.toRectF().translated( m_data->wrappedInput->position() ) );
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return m_data->wrappedInput->inputMethodQuery( query, argument );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt::InputMethodHints QskTextInput::inputMethodHints() const
|
||||
{
|
||||
return m_data->wrappedInput->inputMethodHints();
|
||||
}
|
||||
|
||||
void QskTextInput::setInputMethodHints( Qt::InputMethodHints hints )
|
||||
{
|
||||
if ( m_data->wrappedInput->inputMethodHints() != hints )
|
||||
{
|
||||
m_data->wrappedInput->setInputMethodHints( hints );
|
||||
qskUpdateInputMethod( this, Qt::ImHints );
|
||||
}
|
||||
return hasAcceptableInput() || fixup();
|
||||
}
|
||||
|
||||
void QskTextInput::setupFrom( const QQuickItem* item )
|
||||
|
|
@ -915,4 +414,10 @@ void QskTextInput::setupFrom( const QQuickItem* item )
|
|||
setEchoMode( echoMode );
|
||||
}
|
||||
|
||||
QQuickItem* QskTextInput::wrappedInput()
|
||||
{
|
||||
return m_data->wrappedInput;
|
||||
}
|
||||
|
||||
#include "QskTextInput.moc"
|
||||
#include "moc_QskTextInput.cpp"
|
||||
|
|
|
|||
|
|
@ -6,36 +6,15 @@
|
|||
#ifndef QSK_TEXT_INPUT_H
|
||||
#define QSK_TEXT_INPUT_H
|
||||
|
||||
#include "QskControl.h"
|
||||
#include "QskAbstractTextInput.h"
|
||||
#include "QskTextOptions.h"
|
||||
|
||||
class QValidator;
|
||||
class QskFontRole;
|
||||
|
||||
class QSK_EXPORT QskTextInput : public QskControl
|
||||
class QSK_EXPORT QskTextInput : public QskAbstractTextInput
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString text READ text
|
||||
WRITE setText NOTIFY textChanged USER true )
|
||||
|
||||
Q_PROPERTY( QskFontRole fontRole READ fontRole
|
||||
WRITE setFontRole RESET resetFontRole NOTIFY fontRoleChanged )
|
||||
|
||||
Q_PROPERTY( QFont font READ font )
|
||||
|
||||
Q_PROPERTY( Qt::Alignment alignment READ alignment
|
||||
WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged )
|
||||
|
||||
Q_PROPERTY( QskTextOptions::WrapMode wrapMode READ wrapMode
|
||||
WRITE setWrapMode NOTIFY wrapModeChanged )
|
||||
|
||||
Q_PROPERTY( ActivationModes activationModes READ activationModes
|
||||
WRITE setActivationModes NOTIFY activationModesChanged )
|
||||
|
||||
Q_PROPERTY( bool editing READ isEditing
|
||||
WRITE setEditing NOTIFY editingChanged )
|
||||
|
||||
Q_PROPERTY( EchoMode echoMode READ echoMode
|
||||
WRITE setEchoMode NOTIFY echoModeChanged )
|
||||
|
||||
|
|
@ -47,30 +26,12 @@ class QSK_EXPORT QskTextInput : public QskControl
|
|||
WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay
|
||||
NOTIFY passwordMaskDelayChanged )
|
||||
|
||||
Q_PROPERTY( bool selectByMouse READ selectByMouse
|
||||
WRITE setSelectByMouse )
|
||||
|
||||
using Inherited = QskControl;
|
||||
using Inherited = QskAbstractTextInput;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( TextPanel, Text )
|
||||
QSK_SUBCONTROLS( TextPanel )
|
||||
|
||||
QSK_STATES( ReadOnly, Editing, Error )
|
||||
|
||||
enum ActivationMode : quint8
|
||||
{
|
||||
NoActivation,
|
||||
|
||||
ActivationOnFocus = 1 << 0,
|
||||
ActivationOnMouse = 1 << 1,
|
||||
ActivationOnKey = 1 << 2,
|
||||
|
||||
ActivationOnInput = ActivationOnMouse | ActivationOnKey,
|
||||
ActivationOnAll = ActivationOnFocus | ActivationOnMouse | ActivationOnKey
|
||||
};
|
||||
|
||||
Q_ENUM( ActivationMode )
|
||||
Q_DECLARE_FLAGS( ActivationModes, ActivationMode )
|
||||
QSK_STATES( Error )
|
||||
|
||||
enum EchoMode : quint8
|
||||
{
|
||||
|
|
@ -82,39 +43,11 @@ class QSK_EXPORT QskTextInput : public QskControl
|
|||
|
||||
Q_ENUM( EchoMode )
|
||||
|
||||
QskTextInput( QQuickItem* parent = nullptr );
|
||||
~QskTextInput() override;
|
||||
|
||||
void setupFrom( const QQuickItem* );
|
||||
|
||||
QString text() const;
|
||||
|
||||
void setFontRole( const QskFontRole& role );
|
||||
void resetFontRole();
|
||||
QskFontRole fontRole() const;
|
||||
|
||||
void setAlignment( Qt::Alignment );
|
||||
void resetAlignment();
|
||||
Qt::Alignment alignment() const;
|
||||
|
||||
void setWrapMode( QskTextOptions::WrapMode );
|
||||
QskTextOptions::WrapMode wrapMode() const;
|
||||
|
||||
void setActivationModes( ActivationModes );
|
||||
ActivationModes activationModes() const;
|
||||
|
||||
void setSelectByMouse( bool );
|
||||
bool selectByMouse() const;
|
||||
|
||||
bool isEditing() const;
|
||||
|
||||
QFont font() const;
|
||||
|
||||
bool isReadOnly() const;
|
||||
void setReadOnly( bool );
|
||||
|
||||
int cursorPosition() const;
|
||||
void setCursorPosition( int );
|
||||
|
||||
int maxLength() const;
|
||||
void setMaxLength( int );
|
||||
|
||||
|
|
@ -136,44 +69,14 @@ class QSK_EXPORT QskTextInput : public QskControl
|
|||
void resetPasswordMaskDelay();
|
||||
|
||||
QString displayText() const;
|
||||
QString preeditText() const;
|
||||
|
||||
bool overwriteMode() const;
|
||||
void setOverwriteMode( bool );
|
||||
|
||||
bool hasAcceptableInput() const;
|
||||
bool fixup();
|
||||
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery ) const override;
|
||||
QVariant inputMethodQuery( Qt::InputMethodQuery, const QVariant& argument ) const;
|
||||
|
||||
Qt::InputMethodHints inputMethodHints() const;
|
||||
void setInputMethodHints( Qt::InputMethodHints );
|
||||
bool acceptInput() override;
|
||||
|
||||
void ensureVisible( int position );
|
||||
|
||||
public Q_SLOTS:
|
||||
void clear();
|
||||
void selectAll();
|
||||
void setText( const QString& );
|
||||
void setEditing( bool );
|
||||
|
||||
Q_SIGNALS:
|
||||
void editingChanged( bool );
|
||||
|
||||
void activationModesChanged();
|
||||
void readOnlyChanged( bool );
|
||||
|
||||
void textChanged( const QString& );
|
||||
void displayTextChanged( const QString& );
|
||||
|
||||
void textEdited( const QString& );
|
||||
|
||||
void fontRoleChanged();
|
||||
void alignmentChanged();
|
||||
void wrapModeChanged( QskTextOptions::WrapMode );
|
||||
|
||||
void overwriteModeChanged( bool );
|
||||
void maximumLengthChanged( int );
|
||||
|
||||
void echoModeChanged( EchoMode );
|
||||
|
|
@ -184,32 +87,11 @@ class QSK_EXPORT QskTextInput : public QskControl
|
|||
void inputMaskChanged( const QString& );
|
||||
|
||||
protected:
|
||||
QskTextInput( QQuickItem* parent = nullptr );
|
||||
|
||||
bool event( QEvent* ) override;
|
||||
|
||||
void inputMethodEvent( QInputMethodEvent* ) override;
|
||||
|
||||
void focusInEvent( QFocusEvent* ) override;
|
||||
void focusOutEvent( QFocusEvent* ) override;
|
||||
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseMoveEvent( QMouseEvent* ) override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent* ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void updateLayout() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
QQuickItem* wrappedInput() override final;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QskTextInput::ActivationModes )
|
||||
Q_DECLARE_METATYPE( QskTextInput::ActivationModes )
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
using Q = QskTextInput;
|
||||
|
||||
QSK_SYSTEM_STATE( QskTextInputSkinlet, Selected, QskAspect::FirstSystemState << 3 )
|
||||
|
||||
QskTextInputSkinlet::QskTextInputSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ class QSK_EXPORT QskTextInputSkinlet : public QskSkinlet
|
|||
using Inherited = QskSkinlet;
|
||||
|
||||
public:
|
||||
QSK_STATES( Selected )
|
||||
|
||||
enum NodeRole : quint8
|
||||
{
|
||||
TextPanelRole,
|
||||
|
|
|
|||
Loading…
Reference in New Issue