diff --git a/examples/buttons/buttons.qml b/examples/buttons/buttons.qml index afd690d1..66fbb160 100644 --- a/examples/buttons/buttons.qml +++ b/examples/buttons/buttons.qml @@ -96,8 +96,7 @@ Qsk.Window { text: "Check Me" - flat: true - + section: Qsk.Aspect.Header checkable: true } @@ -105,14 +104,14 @@ Qsk.Window { text: "Push Me" - flat: true + section: Qsk.Aspect.Header } TestButton { text: "Disabled" - flat: true + section: Qsk.Aspect.Header enabled: false } diff --git a/examples/gallery/button/ButtonPage.cpp b/examples/gallery/button/ButtonPage.cpp index 9132dd41..e7fbe51f 100644 --- a/examples/gallery/button/ButtonPage.cpp +++ b/examples/gallery/button/ButtonPage.cpp @@ -32,7 +32,7 @@ namespace const char* texts[] = { "Press Me", "Check Me", "Outlined", "Text" }; const char* graphics[] = { "diamond/khaki", "ellipse/sandybrown" }; - for ( int i = 0; i < 8; i++ ) + for ( int i = 0; i < 6; i++ ) { const int index = i % 2; @@ -49,16 +49,6 @@ namespace { button->setText( texts[ index ] ); } - else if( i == 6 ) - { - button->setSkinStateFlag( QskAbstractButton::Outlined ); - button->setText( texts[ 2 ] ); - } - else if( i == 7 ) - { - button->setSkinStateFlag( QskAbstractButton::TextState ); - button->setText( texts[ 3 ] ); - } } } }; @@ -95,15 +85,14 @@ namespace CheckButtonBox( QQuickItem* parent = nullptr ) : QskLinearBox( Qt::Horizontal, parent ) { - setSpacing( 20 ); + setSpacing( 40 ); setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge ); - for ( auto state : { Qt::Unchecked, Qt::PartiallyChecked, Qt::Checked } ) - { - auto button = new QskCheckBox( this ); - button->setTristate( true ); - button->setCheckState( state ); - } + auto button1 = new QskCheckBox( "Options 1", this ); + button1->setChecked( true ); + + auto button2 = new QskCheckBox( "Options 2", this ); + button2->setLayoutMirroring( true ); } }; } diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index 8e8d622b..0d4bf2a5 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -52,8 +52,6 @@ namespace MenuButton( const QString& text, QQuickItem* parent = nullptr ) : QskPushButton( text, parent ) { - setFlat( true ); // until we have the section bit in QskAspect - connect( this, &QskPushButton::pressed, this, &MenuButton::openMenu ); } @@ -91,14 +89,13 @@ namespace { initSizePolicy( QskSizePolicy::Ignored, QskSizePolicy::Fixed ); + setSection( QskAspect::Header ); + setMargins( 10 ); setBackgroundColor( Qt::lightGray ); { auto button = new QskPushButton( "Skin", this ); -#if 1 - button->setFlat( true ); // until we have the section bit in QskAspect -#endif // transition leads to errors, when changing the tab before being completed. TODO ... connect( button, &QskSwitchButton::clicked, diff --git a/examples/thumbnails/main.cpp b/examples/thumbnails/main.cpp index 0f797af8..a4820c05 100644 --- a/examples/thumbnails/main.cpp +++ b/examples/thumbnails/main.cpp @@ -75,7 +75,7 @@ class Thumbnail : public QskPushButton setGraphic( thumbnailGraphic( color, shape, size ) ); setFixedSize( size ); - setFlat( true ); + setSection( QskAspect::Header ); // to make them flat } private: diff --git a/qmlexport/QskQml.cpp b/qmlexport/QskQml.cpp index 44af924a..441bf47f 100644 --- a/qmlexport/QskQml.cpp +++ b/qmlexport/QskQml.cpp @@ -8,6 +8,7 @@ #include "QskShortcutQml.h" #include "QskMainQml.h" +#include #include #include #include @@ -201,6 +202,7 @@ void QskQml::registerTypes() QSK_REGISTER_GADGET( QskSizePolicy, "SizePolicy" ); QSK_REGISTER_GADGET( QskTextOptions, "TextOptions" ); QSK_REGISTER_GADGET( QskMargins, "Margins" ); + QSK_REGISTER_GADGET( QskAspect, "Aspect" ); } // Support (lists of) GradientStop diff --git a/qskinny.pro b/qskinny.pro index 91e2624a..bdd098d1 100644 --- a/qskinny.pro +++ b/qskinny.pro @@ -7,7 +7,6 @@ SUBDIRS = \ qmlexport \ tools \ support \ - tests \ examples \ playground diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 4fc89578..a8adbde7 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -464,32 +464,6 @@ void Editor::setupPushButton() setShadowMetrics( Q::Panel | Q::Hovered, m_pal.elevationLight1 ); setShadowColor( Q::Panel | Q::Hovered, m_pal.shadow ); - // Outlined and Text: - - const QskStateCombination combination( QskStateCombination::Combination, Q::Outlined | Q::TextState ); - setGradient( Q::Panel, Qt::transparent, combination ); - - setBoxBorderMetrics( Q::Panel, 1, { QskStateCombination::CombinationNoState, Q::Outlined } ); - setBoxBorderColors( Q::Panel | Q::Outlined, m_pal.outline ); - - setPadding( Q::Graphic, 5 ); - - setGradient( Q::Panel | Q::Disabled, Qt::transparent, combination ); - setBoxBorderColors( Q::Panel | Q::Outlined | Q::Disabled, m_pal.onSurface12 ); - - QColor primary08( m_pal.primary ); - primary08.setAlphaF( 0.08 ); - setGradient( Q::Panel | Q::Outlined, primary08, - { QskStateCombination::Combination, - Q::Hovered | Q::Focused | Q::Pressed } ); - setGradient( Q::Panel | Q::TextState, primary08, - { QskStateCombination::Combination, - Q::Hovered | Q::Focused | Q::Pressed } ); - - setColor( Q::Text, m_pal.primary, combination ); - - setColor( Q::Text | Q::Disabled, m_pal.onSurface12, combination ); - setAnimation( Q::Panel | A::Color, qskDuration ); setAnimation( Q::Panel | A::Metric, qskDuration ); setAnimation( Q::Text | A::Color, qskDuration ); diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 8ecb5f98..4f3368a0 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -305,19 +305,29 @@ void Editor::setupCheckBox() const qreal size = qskDpiScaled( 26 ); - setStrutSize( Q::Panel, size, size ); + setSpacing( Q::Panel, qskDpiScaled( 5 ) ); - setPadding( Q::Panel, qskDpiScaled( 5 ) ); - setBoxShape( Q::Panel, qskDpiScaled( 3 ) ); - setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) ); + setStrutSize( Q::Box, size, size ); - setBoxBorderColors( Q::Panel, m_pal.darker125 ); - setGradient( Q::Panel, m_pal.lighter135 ); - setGradient( Q::Panel | Q::Checked, m_pal.highlighted ); + setPadding( Q::Box, qskDpiScaled( 5 ) ); + setBoxShape( Q::Box, qskDpiScaled( 3 ) ); + setBoxBorderMetrics( Q::Box, qskDpiScaled( 1 ) ); - setColor( Q::Indicator, m_pal.lighter135 ); + setBoxBorderColors( Q::Box, m_pal.darker125 ); + setGradient( Q::Box, m_pal.lighter135 ); + setGradient( Q::Box | Q::Checked, m_pal.highlighted ); - setAnimation( Q::Panel | A::Color, qskDuration ); + setGradient( Q::Box | Q::Disabled, m_pal.lighter110 ); + setBoxBorderColors( Q::Box, m_pal.theme ); + + setColor( Q::Indicator, m_pal.darker200 ); + setColor( Q::Indicator | Q::Checked, m_pal.lighter135 ); + + setFlagHint( Q::Text | Q::Disabled | A::Style, Qsk::Sunken ); + setColor( Q::Text, m_pal.themeForeground ); + setColor( Q::Text | Q::Disabled, m_pal.darker200 ); + + setAnimation( Q::Box | A::Color, qskDuration ); } void Editor::setupPopup() @@ -574,15 +584,15 @@ void Editor::setupPushButton() setMetric( Q::Panel | A::Spacing, 4 ); setButton( Q::Panel, Raised ); - setButton( Q::Panel | Q::Flat | Q::Hovered, Raised ); + setButton( Q::Panel | A::Header | Q::Hovered, Raised ); - setButton( Q::Panel | Q::Flat, Flat ); - setButton( Q::Panel | Q::Flat | Q::Disabled, Flat ); + setButton( Q::Panel | A::Header, Flat ); + setButton( Q::Panel | A::Header | Q::Disabled, Flat ); for ( auto state : { Q::Pressed, Q::Checked } ) { setButton( Q::Panel | state, Sunken ); - setButton( Q::Panel | Q::Flat | state, Sunken ); + setButton( Q::Panel | A::Header | state, Sunken ); } setAnimation( Q::Panel | A::Color, qskDuration ); diff --git a/src/common/QskAspect.cpp b/src/common/QskAspect.cpp index b6e4635f..d59ceeee 100644 --- a/src/common/QskAspect.cpp +++ b/src/common/QskAspect.cpp @@ -295,6 +295,9 @@ void qskDebugAspect( QDebug debug, const QMetaObject* metaObject, QskAspect aspe else debug << subControlName; + if ( aspect.section() != QskAspect::Body ) + debug << ", " << qskEnumString( "Section", aspect.section() ); + debug << ", " << qskEnumString( "Type", aspect.type() ); if ( aspect.isAnimator() ) debug << "(A)"; @@ -338,7 +341,7 @@ const char* QskAspect::toPrintable() const QDebug debug( &tmp ); debug << *this; - // we should find a better impementation + // we should find a better implementation static QByteArray bytes[ 10 ]; static int counter = 0; diff --git a/src/common/QskAspect.h b/src/common/QskAspect.h index 2819ae2b..620aeb16 100644 --- a/src/common/QskAspect.h +++ b/src/common/QskAspect.h @@ -27,6 +27,18 @@ class QSK_EXPORT QskAspect static constexpr uint typeCount = 3; + enum Section : quint8 + { + Body = 0, + + Header, + Footer + }; + Q_ENUM( Section ) + + static constexpr uint FirstUserSection = Section::Footer + 1; + static constexpr uint LastSection = ( 1 << 4 ) - 1; + enum Primitive : quint8 { NoPrimitive = 0, @@ -88,11 +100,14 @@ class QSK_EXPORT QskAspect AllStates = 0xFFFF }; + Q_ENUM( State ) Q_DECLARE_FLAGS( States, State ) constexpr QskAspect() noexcept; + constexpr QskAspect( Subcontrol ) noexcept; + constexpr QskAspect( Section ) noexcept; constexpr QskAspect( Type ) noexcept; constexpr QskAspect( Placement ) noexcept; @@ -107,6 +122,7 @@ class QSK_EXPORT QskAspect bool operator<( const QskAspect& ) const noexcept; constexpr QskAspect operator|( Subcontrol ) const noexcept; + constexpr QskAspect operator|( Section ) const noexcept; constexpr QskAspect operator|( Type ) const noexcept; constexpr QskAspect operator|( Primitive ) const noexcept; constexpr QskAspect operator|( Placement ) const noexcept; @@ -134,6 +150,9 @@ class QSK_EXPORT QskAspect constexpr Subcontrol subControl() const noexcept; void setSubControl( Subcontrol ) noexcept; + constexpr Section section() const noexcept; + void setSection( Section ) noexcept; + constexpr Type type() const noexcept; void setType( Type ) noexcept; @@ -175,23 +194,25 @@ class QSK_EXPORT QskAspect static void reservePrimitives( quint8 count ); private: - constexpr QskAspect( Subcontrol, Type, Placement ) noexcept; + constexpr QskAspect( Subcontrol, Section, Type, Placement ) noexcept; - constexpr QskAspect( uint subControl, uint type, bool isAnimator, + constexpr QskAspect( uint subControl, uint section, uint type, bool isAnimator, uint primitive, uint placement, uint states ) noexcept; struct Bits { uint subControl : 12; + uint section : 4; - uint type : 3; + uint type : 3; uint isAnimator : 1; uint primitive : 5; uint placement : 3; - uint reserved1 : 8; + uint reserved1 : 4; + + uint states : 16; - uint states : 16; uint reserved2 : 16; }; @@ -218,34 +239,39 @@ constexpr inline QskAspect::State operator>>( QskAspect::State a, const int b ) } inline constexpr QskAspect::QskAspect() noexcept - : QskAspect( Control, Flag, NoPlacement ) + : QskAspect( Control, Body, Flag, NoPlacement ) { } inline constexpr QskAspect::QskAspect( Subcontrol subControl ) noexcept - : QskAspect( subControl, Flag, NoPlacement ) + : QskAspect( subControl, Body, Flag, NoPlacement ) +{ +} + +inline constexpr QskAspect::QskAspect( Section section ) noexcept + : QskAspect( Control, section, Flag, NoPlacement ) { } inline constexpr QskAspect::QskAspect( Type type ) noexcept - : QskAspect( Control, type, NoPlacement ) + : QskAspect( Control, Body, type, NoPlacement ) { } inline constexpr QskAspect::QskAspect( Placement placement ) noexcept - : QskAspect( Control, Flag, placement ) + : QskAspect( Control, Body, Flag, placement ) { } inline constexpr QskAspect::QskAspect( - Subcontrol subControl, Type type, Placement placement ) noexcept - : QskAspect( subControl, type, false, 0, placement, NoState ) + Subcontrol subControl, Section section, Type type, Placement placement ) noexcept + : QskAspect( subControl, section, type, false, 0, placement, NoState ) { } -inline constexpr QskAspect::QskAspect( uint subControl, uint type, bool isAnimator, +inline constexpr QskAspect::QskAspect( uint subControl, uint section, uint type, bool isAnimator, uint primitive, uint placement, uint states ) noexcept - : m_bits { subControl, type, isAnimator, primitive, placement, 0, states, 0 } + : m_bits { subControl, section, type, isAnimator, primitive, placement, 0, states, 0 } { } @@ -266,32 +292,38 @@ inline bool QskAspect::operator<( const QskAspect& other ) const noexcept inline constexpr QskAspect QskAspect::operator|( Subcontrol subControl ) const noexcept { - return QskAspect( subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, m_bits.placement, m_bits.states ); + return QskAspect( subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states ); +} + +inline constexpr QskAspect QskAspect::operator|( Section section ) const noexcept +{ + return QskAspect( m_bits.subControl, section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states ); } inline constexpr QskAspect QskAspect::operator|( Type type ) const noexcept { - return QskAspect( m_bits.subControl, type, m_bits.isAnimator, - m_bits.primitive, m_bits.placement, m_bits.states ); + return QskAspect( m_bits.subControl, m_bits.section, type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states ); } inline constexpr QskAspect QskAspect::operator|( Primitive primitive ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - primitive, m_bits.placement, m_bits.states ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, primitive, m_bits.placement, m_bits.states ); } inline constexpr QskAspect QskAspect::operator|( Placement placement ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, placement, m_bits.states ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, placement, m_bits.states ); } inline constexpr QskAspect QskAspect::operator|( State state ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, m_bits.placement, m_bits.states | state ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states | state ); } inline QskAspect& QskAspect::operator|=( State state ) noexcept @@ -302,7 +334,7 @@ inline QskAspect& QskAspect::operator|=( State state ) noexcept inline constexpr QskAspect QskAspect::operator&( State state ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states & state ); } @@ -314,7 +346,7 @@ inline QskAspect& QskAspect::operator&=( State state ) noexcept inline constexpr QskAspect QskAspect::operator|( States states ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states | states ); } @@ -326,8 +358,8 @@ inline QskAspect& QskAspect::operator|=( States states ) noexcept inline constexpr QskAspect QskAspect::operator&( States states ) const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, m_bits.placement, m_bits.states & states ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, m_bits.states & states ); } inline QskAspect& QskAspect::operator&=( States states ) noexcept @@ -338,14 +370,14 @@ inline QskAspect& QskAspect::operator&=( States states ) noexcept inline constexpr QskAspect QskAspect::stateless() const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, m_bits.placement, 0 ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, m_bits.placement, 0 ); } inline constexpr QskAspect QskAspect::trunk() const noexcept { - return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, - m_bits.primitive, 0, 0 ); + return QskAspect( m_bits.subControl, m_bits.section, m_bits.type, + m_bits.isAnimator, m_bits.primitive, 0, 0 ); } inline constexpr quint64 QskAspect::value() const noexcept @@ -373,6 +405,16 @@ inline void QskAspect::setSubControl( Subcontrol subControl ) noexcept m_bits.subControl = subControl; } +inline constexpr QskAspect::Section QskAspect::section() const noexcept +{ + return static_cast< Section >( m_bits.section ); +} + +inline void QskAspect::setSection( Section section ) noexcept +{ + m_bits.section = section; +} + inline constexpr QskAspect::Type QskAspect::type() const noexcept { return static_cast< Type >( m_bits.type ); @@ -490,6 +532,12 @@ inline constexpr QskAspect operator|( return aspect | subControl; } +inline constexpr QskAspect operator|( + QskAspect::Section section, const QskAspect& aspect ) noexcept +{ + return aspect | section; +} + inline constexpr QskAspect operator|( QskAspect::Type type, const QskAspect& aspect ) noexcept { @@ -502,6 +550,18 @@ inline constexpr QskAspect operator|( return aspect | placement; } +inline constexpr QskAspect operator|( + QskAspect::Subcontrol subControl, QskAspect::Section section ) noexcept +{ + return QskAspect( subControl ) | section; +} + +inline constexpr QskAspect operator|( + QskAspect::Section section, QskAspect::Subcontrol subControl ) noexcept +{ + return subControl | section; +} + inline constexpr QskAspect operator|( QskAspect::Subcontrol subControl, QskAspect::Type type ) noexcept { diff --git a/src/controls/QskAbstractButton.cpp b/src/controls/QskAbstractButton.cpp index cb3f4ef9..f286f881 100644 --- a/src/controls/QskAbstractButton.cpp +++ b/src/controls/QskAbstractButton.cpp @@ -10,11 +10,6 @@ #include -// Flat is no state - we need to get rid of it. TODO ... -QSK_SYSTEM_STATE( QskAbstractButton, Flat, QskAspect::FirstSystemState << 1 ) -QSK_SYSTEM_STATE( QskAbstractButton, Outlined, QskAspect::FirstSystemState << 2 ) -QSK_SYSTEM_STATE( QskAbstractButton, TextState, QskAspect::FirstSystemState << 3 ) - QSK_SYSTEM_STATE( QskAbstractButton, Checked, QskAspect::LastSystemState >> 3 ) QSK_SYSTEM_STATE( QskAbstractButton, Pressed, QskAspect::LastSystemState >> 2 ) diff --git a/src/controls/QskAbstractButton.h b/src/controls/QskAbstractButton.h index 70ecb4f1..af1a1038 100644 --- a/src/controls/QskAbstractButton.h +++ b/src/controls/QskAbstractButton.h @@ -33,7 +33,7 @@ class QSK_EXPORT QskAbstractButton : public QskControl using Inherited = QskControl; public: - QSK_STATES( Flat, Outlined, TextState, Checked, Pressed ) + QSK_STATES( Checked, Pressed ) QskAbstractButton( QQuickItem* parent = nullptr ); ~QskAbstractButton() override; diff --git a/src/controls/QskCheckBox.cpp b/src/controls/QskCheckBox.cpp index 95b55191..425772e1 100644 --- a/src/controls/QskCheckBox.cpp +++ b/src/controls/QskCheckBox.cpp @@ -4,50 +4,37 @@ *****************************************************************************/ #include "QskCheckBox.h" -#include "QskAspect.h" - -#include QSK_SUBCONTROL( QskCheckBox, Panel ) +QSK_SUBCONTROL( QskCheckBox, Box ) QSK_SUBCONTROL( QskCheckBox, Indicator ) - -QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 ) +QSK_SUBCONTROL( QskCheckBox, Text ) class QskCheckBox::PrivateData { public: - PrivateData() - : checkState( Qt::Unchecked ) - , checkStateChanging( false ) - , toggleChanging( false ) - , tristate( false ) + PrivateData( const QString& text ) + : text( text ) { } - QSet< QskAbstractButton* > group; - - int groupItemsChecked = 0; - - Qt::CheckState checkState : 2; - bool checkStateChanging : 1; - bool toggleChanging : 1; - bool tristate : 1; + QString text; }; QskCheckBox::QskCheckBox( QQuickItem* parent ) - : Inherited( parent ) - , m_data( new PrivateData() ) + : QskCheckBox( QString(), parent ) { - setAcceptHoverEvents( true ); - initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); +} - connect( this, &QskCheckBox::checkedChanged, this, - [ this ]( bool on ) { setCheckStateInternal( on ? Qt::Checked : Qt::Unchecked ); } ); +QskCheckBox::QskCheckBox( const QString& text, QQuickItem* parent ) + : Inherited( parent ) + , m_data( new PrivateData( text ) ) +{ + initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); } QskCheckBox::~QskCheckBox() { - Q_EMIT removeFromAllGroupsRequested(); } bool QskCheckBox::isCheckable() const @@ -55,130 +42,33 @@ bool QskCheckBox::isCheckable() const return true; } -Qt::CheckState QskCheckBox::checkState() const +void QskCheckBox::setText( const QString& text ) { - return m_data->checkState; -} - -void QskCheckBox::setCheckStateInternal( Qt::CheckState checkState ) -{ - if( m_data->checkStateChanging ) - return; - - setSkinStateFlag( PartiallyChecked, checkState == Qt::PartiallyChecked ); - - m_data->checkState = checkState; - Q_EMIT checkStateChanged( checkState ); -} - -void QskCheckBox::setCheckState( Qt::CheckState checkState ) -{ - if( checkState == m_data->checkState ) - return; - - m_data->checkStateChanging = true; - - if( checkState == Qt::PartiallyChecked ) + if ( text != m_data->text ) { - setChecked( true ); - setTristate( true ); - } - else - { - setChecked( checkState == Qt::Checked ); - } + m_data->text = text; - m_data->checkStateChanging = false; + resetImplicitSize(); + update(); - setCheckStateInternal( checkState ); -} - -bool QskCheckBox::isTristate() const -{ - return m_data->tristate; -} - -void QskCheckBox::setTristate( bool tristate ) -{ - if( m_data->tristate != tristate ) - { - m_data->tristate = tristate; - Q_EMIT tristateChanged( tristate ); + Q_EMIT textChanged(); } } -void QskCheckBox::updated() +QString QskCheckBox::text() const { - if( m_data->toggleChanging ) - return; - - const auto& groupItemsChecked = m_data->groupItemsChecked; - - if( groupItemsChecked == m_data->group.size() ) - { - setCheckState( Qt::Checked ); - } - else if ( groupItemsChecked == 0 ) - { - setCheckState( Qt::Unchecked ); - } - else - { - setCheckState( Qt::PartiallyChecked ); - } + return m_data->text; } -void QskCheckBox::addToGroup( QskCheckBox* groupItem ) +void QskCheckBox::changeEvent( QEvent* event ) { - if( m_data->group.contains( groupItem ) ) - return; - - m_data->group.insert( groupItem ); - - if( groupItem->checkState() == Qt::Checked ) - m_data->groupItemsChecked++; - - updated(); - - connect( this, &QskCheckBox::checkStateChanged, - groupItem, [ this, groupItem ]( Qt::CheckState checkState ) + if ( event->type() == QEvent::LayoutDirectionChange ) { - if( checkState == Qt::Checked ) - { - m_data->toggleChanging = true; - groupItem->setChecked( true ); - m_data->groupItemsChecked = m_data->group.size(); - m_data->toggleChanging = false; - } - else if ( checkState == Qt::Unchecked ) - { - m_data->toggleChanging = true; - groupItem->setChecked( false ); - m_data->groupItemsChecked = 0; - m_data->toggleChanging = false; - } - } ); + if ( !m_data->text.isEmpty() ) + update(); + } - connect( groupItem, &QskAbstractButton::toggled, - this, [ this ]( bool toggled ) - { - m_data->groupItemsChecked += toggled ? 1 : -1; - updated(); - } ); - - connect( groupItem, &QskCheckBox::removeFromAllGroupsRequested, - this, [ this, groupItem ]( ) { removeFromGroup( groupItem ); } ); -} - -void QskCheckBox::removeFromGroup( QskCheckBox* groupItem ) -{ - if( !m_data->group.remove( groupItem ) ) - return; - - if( groupItem->checkState() == Qt::Checked ) - m_data->groupItemsChecked--; - - updated(); + Inherited::changeEvent( event ); } #include "moc_QskCheckBox.cpp" diff --git a/src/controls/QskCheckBox.h b/src/controls/QskCheckBox.h index 9a2fb36e..0f67fd74 100644 --- a/src/controls/QskCheckBox.h +++ b/src/controls/QskCheckBox.h @@ -12,41 +12,32 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton { Q_OBJECT - Q_PROPERTY( Qt::CheckState checkState READ checkState - WRITE setCheckState NOTIFY checkStateChanged FINAL ) - - Q_PROPERTY( bool tristate READ isTristate - WRITE setTristate NOTIFY tristateChanged FINAL ) + Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged FINAL ) using Inherited = QskAbstractButton; public: - QSK_SUBCONTROLS( Panel, Indicator ) - QSK_STATES( PartiallyChecked ) + QSK_SUBCONTROLS( Panel, Box, Indicator, Text ) QskCheckBox( QQuickItem* parent = nullptr ); + QskCheckBox( const QString&, QQuickItem* parent = nullptr ); + ~QskCheckBox() override; - Qt::CheckState checkState() const; - bool isTristate() const; + QString text() const; + bool isCheckable() const override final; - void addToGroup( QskCheckBox* ); - void removeFromGroup( QskCheckBox* ); - public Q_SLOTS: - void setCheckState( Qt::CheckState ); - void setTristate( bool triState = true ); + void setText( const QString& ); Q_SIGNALS: - void checkStateChanged( Qt::CheckState ); - void tristateChanged( bool ); - void removeFromAllGroupsRequested(); + void textChanged(); + + protected: + void changeEvent( QEvent* ) override; private: - void setCheckStateInternal( Qt::CheckState ); - void updated(); - class PrivateData; std::unique_ptr< PrivateData > m_data; }; diff --git a/src/controls/QskCheckBoxSkinlet.cpp b/src/controls/QskCheckBoxSkinlet.cpp index 8ed32b20..0b13aba8 100644 --- a/src/controls/QskCheckBoxSkinlet.cpp +++ b/src/controls/QskCheckBoxSkinlet.cpp @@ -5,76 +5,17 @@ #include "QskCheckBoxSkinlet.h" #include "QskCheckBox.h" -#include "QskSGNode.h" - -#include -#include - -namespace -{ - class IndicatorNode : public QSGGeometryNode - { - public: - IndicatorNode() - : m_geometry( QSGGeometry::defaultAttributes_Point2D(), 3 ) - { - m_geometry.setDrawingMode( QSGGeometry::DrawLineStrip ); - m_geometry.setLineWidth( 2 ); - setGeometry( &m_geometry ); - - setMaterial( &m_material ); - } - - void update( bool isPartially, const QRectF& rect, const QColor& color ) - { - if ( color != m_material.color() ) - { - m_material.setColor( color ); - markDirty( QSGNode::DirtyMaterial ); - } - - if ( rect != m_rect || isPartially != m_isPartially ) - { - m_rect = rect; - m_isPartially = isPartially; - - const auto x = rect.x(); - const auto y = rect.y(); - const auto w = rect.width(); - const auto h = rect.height(); - - auto points = m_geometry.vertexDataAsPoint2D(); - - if ( isPartially ) - { - points[0].set( x, y + h / 2 ); - points[1] = points[0]; - points[2].set( x + w, y + h / 2 ); - } - else - { - points[0].set( x, y + h / 2 ); - points[1].set( x + w / 3, y + h ); - points[2].set( x + w, y ); - } - - markDirty( QSGNode::DirtyGeometry ); - } - } - - private: - QSGFlatColorMaterial m_material; - QSGGeometry m_geometry; - - QRectF m_rect; - bool m_isPartially; - }; -} +#include "QskTextOptions.h" +#include "QskFunctions.h" +#include "QskGraphic.h" +#include "QskStandardSymbol.h" +#include "QskColorFilter.h" +#include "QskSkin.h" QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin ) : QskSkinlet( skin ) { - setNodeRoles( { PanelRole, IndicatorRole } ); + setNodeRoles( { BoxRole, IndicatorRole, TextRole } ); } QskCheckBoxSkinlet::~QskCheckBoxSkinlet() @@ -84,12 +25,66 @@ QskCheckBoxSkinlet::~QskCheckBoxSkinlet() QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { - if ( subControl == QskCheckBox::Indicator ) - return skinnable->innerBox( QskCheckBox::Panel, contentsRect ); + const auto checkBox = static_cast< const QskCheckBox* >( skinnable ); + + if ( subControl == QskCheckBox::Panel ) + { + return contentsRect; + } + else if ( subControl == QskCheckBox::Box ) + { + return boxRect( checkBox, contentsRect ); + } + else if ( subControl == QskCheckBox::Indicator ) + { + const auto boxRect = subControlRect( skinnable, contentsRect, QskCheckBox::Box ); + return skinnable->innerBox( QskCheckBox::Box, boxRect ); + + return skinnable->innerBox( QskCheckBox::Box, contentsRect ); + } + else if ( subControl == QskCheckBox::Text ) + { + return textRect( checkBox, contentsRect ); + } return contentsRect; } +QRectF QskCheckBoxSkinlet::textRect( + const QskCheckBox* checkBox, const QRectF& contentsRect ) const +{ + const auto boxRect = subControlRect( checkBox, contentsRect, QskCheckBox::Box ); + const qreal spacing = checkBox->spacingHint( QskCheckBox::Panel ); + + auto r = subControlRect( checkBox, contentsRect, QskCheckBox::Panel ); + r = checkBox->innerBox( QskCheckBox::Panel, r ); + + if ( checkBox->layoutMirroring() ) + r.setRight( boxRect.left() - spacing ); + else + r.setLeft( boxRect.right() + spacing ); + + return r; +} + +QRectF QskCheckBoxSkinlet::boxRect( + const QskCheckBox* checkBox, const QRectF& contentsRect ) const +{ + const auto size = checkBox->strutSizeHint( QskCheckBox::Box ); + + auto r = checkBox->innerBox( QskCheckBox::Panel, contentsRect ); + + if ( checkBox->layoutMirroring() ) + r.setLeft( r.right() - size.width() ); + else + r.setWidth( size.width() ); + + r.setTop( r.top() + 0.5 * ( r.height() - size.height() ) ); + r.setHeight( size.height() ); + + return r; +} + QSGNode* QskCheckBoxSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { @@ -100,8 +95,14 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode( case PanelRole: return updateBoxNode( skinnable, node, QskCheckBox::Panel ); + case BoxRole: + return updateBoxNode( skinnable, node, QskCheckBox::Box ); + case IndicatorRole: return updateIndicatorNode( checkBox, node ); + + case TextRole: + return updateTextNode( checkBox, node ); } return Inherited::updateSubNode( skinnable, nodeRole, node ); @@ -109,27 +110,77 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode( QSGNode* QskCheckBoxSkinlet::updateIndicatorNode( const QskCheckBox* checkBox, QSGNode* node ) const +{ + auto symbol = QskStandardSymbol::CheckMark; + if ( !checkBox->isChecked() ) + { +#if 0 + symbol = QskStandardSymbol::NoSymbol; +#else + symbol = QskStandardSymbol::CrossMark; +#endif + } + + auto graphic = checkBox->effectiveSkin()->symbol( symbol ); + +#if 1 + /* + Our default skins do not have the concept of colorRoles + implemented. Until then we do the recoloring manually here + */ + QskColorFilter filter; + filter.addColorSubstitution( Qt::black, + checkBox->color( QskCheckBox::Indicator ).rgba() ); + + graphic = QskGraphic::fromGraphic( graphic, filter ); +#endif + + return updateGraphicNode( checkBox, node, graphic, QskCheckBox::Indicator ); +} + +QSGNode* QskCheckBoxSkinlet::updateTextNode( + const QskCheckBox* checkBox, QSGNode* node ) const { using Q = QskCheckBox; - const auto state = checkBox->checkState(); - if ( state == Qt::Unchecked ) - return nullptr; + const auto rect = checkBox->subControlRect( Q::Text ); + const auto alignH = checkBox->layoutMirroring() ? Qt::AlignRight : Qt::AlignLeft; - const auto rect = checkBox->subControlRect( Q::Indicator ); - if ( rect.isEmpty() ) - return nullptr; + QskTextOptions textOptions; + textOptions.setElideMode( Qt::ElideMiddle ); - auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node ); - indicatorNode->update( state != Qt::Checked, rect, checkBox->color( Q::Indicator ) ); - - return indicatorNode; + return QskSkinlet::updateTextNode( checkBox, node, rect, alignH | Qt::AlignVCenter, + checkBox->text(), textOptions, QskCheckBox::Text ); } QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable, - Qt::SizeHint, const QSizeF& ) const + Qt::SizeHint which, const QSizeF& ) const { - return skinnable->strutSizeHint( QskCheckBox::Panel ); + using Q = QskCheckBox; + + if ( which == Qt::MaximumSize ) + return QSizeF(); + + auto checkBox = static_cast< const QskCheckBox* >( skinnable ); + + auto size = skinnable->strutSizeHint( QskCheckBox::Box ); + size = skinnable->outerBoxSize( Q::Panel, size ); + + auto text = checkBox->text(); + if ( !text.isEmpty() ) + { + qreal extra = skinnable->spacingHint( Q::Panel ); + + if ( which == Qt::MinimumSize ) + text = 'W'; + + const auto font = skinnable->effectiveFont( Q::Text ); + extra += qskHorizontalAdvance( font, text ); + + size.setWidth( size.width() + extra ); + } + + return size.expandedTo( skinnable->strutSizeHint( Q::Panel ) ); } #include "moc_QskCheckBoxSkinlet.cpp" diff --git a/src/controls/QskCheckBoxSkinlet.h b/src/controls/QskCheckBoxSkinlet.h index 9164deb9..770d572b 100644 --- a/src/controls/QskCheckBoxSkinlet.h +++ b/src/controls/QskCheckBoxSkinlet.h @@ -20,7 +20,9 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet enum NodeRole { PanelRole, + BoxRole, IndicatorRole, + TextRole, RoleCount }; @@ -38,8 +40,12 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; - protected: - virtual QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const; + private: + QRectF textRect( const QskCheckBox*, const QRectF& ) const; + QRectF boxRect( const QskCheckBox*, const QRectF& ) const; + + QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const; + QSGNode* updateTextNode( const QskCheckBox*, QSGNode* ) const; }; #endif diff --git a/src/controls/QskControl.cpp b/src/controls/QskControl.cpp index d75d3e85..7f76a2e3 100644 --- a/src/controls/QskControl.cpp +++ b/src/controls/QskControl.cpp @@ -38,6 +38,7 @@ QskControl::QskControl( QQuickItem* parent ) { // inheriting attributes from parent QskControlPrivate::resolveLocale( this ); + QskControlPrivate::resolveSection( this ); } } @@ -240,9 +241,12 @@ void QskControl::setLocale( const QLocale& locale ) if ( d->locale != locale ) { + extern void qskInheritLocale( QObject*, const QLocale& ); + d->locale = locale; qskSendEventTo( this, QEvent::LocaleChange ); - qskSetup->inheritLocale( this, locale ); + + qskInheritLocale( this, locale ); } } @@ -257,6 +261,47 @@ void QskControl::resetLocale() } } +void QskControl::setSection( QskAspect::Section section ) +{ + if ( section > QskAspect::LastSection ) + { + qWarning() << "Trying to set an invalid section, ignored"; + return; + } + + Q_D( QskControl ); + + d->explicitSection = true; + + if ( d->section != section ) + { + extern void qskInheritSection( QskControl*, const QskAspect::Section ); + + d->section = section; + + update(); + resetImplicitSize(); + + qskInheritSection( this, section ); + } +} + +void QskControl::resetSection() +{ + Q_D( QskControl ); + + if ( d->explicitSection ) + { + d->explicitSection = false; + QskControlPrivate::resolveSection( this ); + } +} + +QskAspect::Section QskControl::section() const +{ + return static_cast< QskAspect::Section >( d_func()->section ); +} + void QskControl::initSizePolicy( QskSizePolicy::Policy horizontalPolicy, QskSizePolicy::Policy verticalPolicy ) @@ -809,6 +854,9 @@ void QskControl::itemChange( QQuickItem::ItemChange change, { if ( !d_func()->explicitLocale ) QskControlPrivate::resolveLocale( this ); + + if ( !d_func()->explicitSection ) + QskControlPrivate::resolveSection( this ); } #if 1 diff --git a/src/controls/QskControl.h b/src/controls/QskControl.h index f93fc8bf..01387f59 100644 --- a/src/controls/QskControl.h +++ b/src/controls/QskControl.h @@ -26,6 +26,9 @@ class QSK_EXPORT QskControl : public QskQuickItem, public QskSkinnable Q_PROPERTY( QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged ) + Q_PROPERTY( QskAspect::Section section READ section + WRITE setSection RESET resetSection NOTIFY sectionChanged ) + Q_PROPERTY( bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground ) @@ -104,6 +107,10 @@ class QSK_EXPORT QskControl : public QskQuickItem, public QskSkinnable void setFocusPolicy( Qt::FocusPolicy ); Qt::FocusPolicy focusPolicy() const; + void setSection( QskAspect::Section ); + void resetSection(); + QskAspect::Section section() const override final; + void setSizePolicy( QskSizePolicy ); void setSizePolicy( QskSizePolicy::Policy, QskSizePolicy::Policy ); void setSizePolicy( Qt::Orientation, QskSizePolicy::Policy ); @@ -175,6 +182,7 @@ class QSK_EXPORT QskControl : public QskQuickItem, public QskSkinnable Q_SIGNALS: void backgroundChanged(); + void sectionChanged( QskAspect::Section ); void marginsChanged( const QMarginsF& ); void focusIndicatorRectChanged(); void localeChanged( const QLocale& ); diff --git a/src/controls/QskControlPrivate.cpp b/src/controls/QskControlPrivate.cpp index b7571af0..96f9caf0 100644 --- a/src/controls/QskControlPrivate.cpp +++ b/src/controls/QskControlPrivate.cpp @@ -6,6 +6,8 @@ #include "QskControlPrivate.h" #include "QskSetup.h" #include "QskLayoutMetrics.h" +#include "QskObjectTree.h" +#include "QskWindow.h" static inline void qskSendEventTo( QObject* object, QEvent::Type type ) { @@ -22,6 +24,108 @@ static inline QPointF qskScenePosition( const QMouseEvent* event ) #endif } +extern bool qskInheritLocale( QskWindow*, const QLocale& ); + +namespace +{ + class VisitorLocale final : public QskObjectTree::ResolveVisitor< QLocale > + { + public: + VisitorLocale() + : ResolveVisitor< QLocale >( "locale" ) + { + } + + private: + bool setImplicitValue( QskControl* control, + const QLocale& locale ) override + { + return QskControlPrivate::inheritLocale( control, locale ); + } + + bool setImplicitValue( QskWindow* window, + const QLocale& locale ) override + { + return qskInheritLocale( window, locale ); + } + + QLocale value( const QskControl* control ) const override + { + return control->locale(); + } + + QLocale value( const QskWindow* window ) const override + { + return window->locale(); + } + }; + + class VisitorSection final : public QskObjectTree::ResolveVisitor< QskAspect::Section > + { + public: + VisitorSection() + : ResolveVisitor< QskAspect::Section >( "section" ) + { + } + + private: + bool setImplicitValue( QskControl* control, + const QskAspect::Section& section ) override + { + return QskControlPrivate::inheritSection( control, section ); + } + + bool setImplicitValue( QskWindow*, const QskAspect::Section& ) override + { + return true; + } + + QskAspect::Section value( const QskControl* control ) const override + { + return control->section(); + } + + QskAspect::Section value( const QskWindow* ) const override + { + return QskAspect::Body; + } + }; +} + +QLocale qskInheritedLocale( const QObject* object ) +{ + VisitorLocale visitor; + visitor.setResolveValue( QLocale() ); + + QskObjectTree::traverseUp( const_cast< QObject* >( object ), visitor ); + return visitor.resolveValue(); +} + +void qskInheritLocale( QObject* object, const QLocale& locale ) +{ + VisitorLocale visitor; + visitor.setResolveValue( locale ); + + QskObjectTree::traverseDown( object, visitor ); +} + +static QskAspect::Section qskInheritedSection( const QskControl* control ) +{ + VisitorSection visitor; + visitor.setResolveValue( QskAspect::Body ); + + QskObjectTree::traverseUp( const_cast< QskControl* >( control ), visitor ); + return visitor.resolveValue(); +} + +void qskInheritSection( QskControl* control, QskAspect::Section section ) +{ + VisitorSection visitor; + visitor.setResolveValue( section ); + + QskObjectTree::traverseDown( control, visitor ); +} + /* Qt 5.12: sizeof( QQuickItemPrivate::ExtraData ) -> 184 @@ -52,6 +156,7 @@ QskControlPrivate::QskControlPrivate() , hiddenPlacementPolicy( 0 ) , layoutAlignmentHint( 0 ) , explicitLocale( false ) + , explicitSection( false ) , autoFillBackground( false ) , autoLayoutChildren( false ) , focusPolicy( Qt::NoFocus ) @@ -255,7 +360,7 @@ bool QskControlPrivate::inheritLocale( QskControl* control, const QLocale& local void QskControlPrivate::resolveLocale( QskControl* control ) { - const auto locale = qskSetup->inheritedLocale( control ); + const auto locale = qskInheritedLocale( control ); auto d = static_cast< QskControlPrivate* >( QQuickItemPrivate::get( control ) ); if ( d->locale != locale ) @@ -263,7 +368,39 @@ void QskControlPrivate::resolveLocale( QskControl* control ) d->locale = locale; qskSendEventTo( control, QEvent::LocaleChange ); - qskSetup->inheritLocale( control, locale ); + qskInheritLocale( control, locale ); + } +} + +bool QskControlPrivate::inheritSection( + QskControl* control, const QskAspect::Section section ) +{ + auto d = static_cast< QskControlPrivate* >( QQuickItemPrivate::get( control ) ); + + if ( d->explicitSection || d->section == section ) + return true; + + d->section = section; + + control->update(); + control->resetImplicitSize(); + + return false; +} + +void QskControlPrivate::resolveSection( QskControl* control ) +{ + const auto section = qskInheritedSection( control ); + + auto d = static_cast< QskControlPrivate* >( QQuickItemPrivate::get( control ) ); + if ( d->section != section ) + { + d->section = section; + + control->update(); + control->resetImplicitSize(); + + qskInheritSection( control, section ); } } diff --git a/src/controls/QskControlPrivate.h b/src/controls/QskControlPrivate.h index 61fe3be7..d1854d8e 100644 --- a/src/controls/QskControlPrivate.h +++ b/src/controls/QskControlPrivate.h @@ -18,6 +18,9 @@ class QskControlPrivate : public QskQuickItemPrivate static bool inheritLocale( QskControl*, const QLocale& ); static void resolveLocale( QskControl* ); + static bool inheritSection( QskControl*, QskAspect::Section ); + static void resolveSection( QskControl* ); + protected: QskControlPrivate(); ~QskControlPrivate() override; @@ -51,8 +54,10 @@ class QskControlPrivate : public QskQuickItemPrivate unsigned int hiddenPlacementPolicy : 2; unsigned int layoutAlignmentHint : 8; + unsigned int section : 4; bool explicitLocale : 1; + bool explicitSection : 1; bool autoFillBackground : 1; bool autoLayoutChildren : 1; diff --git a/src/controls/QskPushButton.cpp b/src/controls/QskPushButton.cpp index 5ee33f25..dde79462 100644 --- a/src/controls/QskPushButton.cpp +++ b/src/controls/QskPushButton.cpp @@ -100,20 +100,6 @@ QskBoxShapeMetrics QskPushButton::shape() const return boxShapeHint( Panel ); } -void QskPushButton::setFlat( bool on ) -{ - if ( on != isFlat() ) - { - setSkinStateFlag( Flat, on ); - Q_EMIT flatChanged(); - } -} - -bool QskPushButton::isFlat() const -{ - return hasSkinState( Flat ); -} - void QskPushButton::setText( const QString& text ) { if ( text != m_data->text ) diff --git a/src/controls/QskPushButton.h b/src/controls/QskPushButton.h index 0a9cc6b8..25d83d92 100644 --- a/src/controls/QskPushButton.h +++ b/src/controls/QskPushButton.h @@ -36,8 +36,6 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton Q_PROPERTY( bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL ) - Q_PROPERTY( bool flat READ isFlat WRITE setFlat NOTIFY flatChanged FINAL ) - Q_PROPERTY( QskBoxShapeMetrics shape READ shape WRITE setShape RESET resetShape NOTIFY shapeChanged ) @@ -70,9 +68,6 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton void resetGraphicSourceSize(); - void setFlat( bool ); - bool isFlat() const; - QFont font() const; QRectF layoutRectForSize( const QSizeF& ) const override; @@ -89,7 +84,6 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton void shapeChanged(); void textChanged(); void textOptionsChanged(); - void flatChanged(); void graphicChanged(); void graphicSourceChanged(); void graphicSourceSizeChanged(); diff --git a/src/controls/QskPushButtonSkinlet.cpp b/src/controls/QskPushButtonSkinlet.cpp index 45bd1531..b42e85fa 100644 --- a/src/controls/QskPushButtonSkinlet.cpp +++ b/src/controls/QskPushButtonSkinlet.cpp @@ -203,7 +203,7 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable, QSizeF size( 0, 0 ); - const QFontMetricsF fm( button->font() ); + const QFontMetricsF fm( button->effectiveFont( QskPushButton::Text ) ); if ( !button->text().isEmpty() ) { diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index b6f54789..93fd7484 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -18,7 +18,8 @@ QskSegmentedBarSkinlet::QskSegmentedBarSkinlet( QskSkin* skin ) : Inherited( skin ) { - setNodeRoles( { PanelRole, SegmentRole, SeparatorRole, CursorRole, TextRole, GraphicRole } ); + setNodeRoles( { PanelRole, SegmentRole, SeparatorRole, + CursorRole, TextRole, GraphicRole } ); } QskSegmentedBarSkinlet::~QskSegmentedBarSkinlet() = default; @@ -104,6 +105,9 @@ QRectF QskSegmentedBarSkinlet::separatorRect( { using Q = QskSegmentedBar; + if( index == bar->count() - 1 ) + return QRectF(); // no separator behind the last segment + auto rect = segmentRect( bar, contentsRect, index ); auto sh = bar->sizeHint(); @@ -312,25 +316,11 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index ); - if ( subControl == Q::Segment ) + if ( subControl == Q::Segment || subControl == Q::Separator ) { return updateBoxNode( skinnable, node, rect, subControl ); } - if( subControl == Q::Separator ) - { - if( index == bar->count() - 1 ) - { - return nullptr; - } - else - { - const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index ); - - return updateBoxNode( skinnable, node, rect, subControl ); - } - } - const auto alignment = bar->alignmentHint( subControl, Qt::AlignCenter ); if ( subControl == Q::Text ) diff --git a/src/controls/QskSetup.cpp b/src/controls/QskSetup.cpp index 6b91a4d6..bf5bd8ee 100644 --- a/src/controls/QskSetup.cpp +++ b/src/controls/QskSetup.cpp @@ -7,7 +7,6 @@ #include "QskControl.h" #include "QskControlPrivate.h" #include "QskGraphicProviderMap.h" -#include "QskObjectTree.h" #include "QskSkin.h" #include "QskSkinManager.h" #include "QskWindow.h" @@ -74,43 +73,6 @@ static void qskApplicationFilter() Q_CONSTRUCTOR_FUNCTION( qskApplicationHook ) Q_COREAPP_STARTUP_FUNCTION( qskApplicationFilter ) -extern bool qskInheritLocale( QskWindow*, const QLocale& ); - -namespace -{ - class VisitorLocale final : public QskObjectTree::ResolveVisitor< QLocale > - { - public: - VisitorLocale() - : ResolveVisitor< QLocale >( "locale" ) - { - } - - private: - bool setImplicitValue( QskControl* control, - const QLocale& locale ) override - { - return QskControlPrivate::inheritLocale( control, locale ); - } - - bool setImplicitValue( QskWindow* window, - const QLocale& locale ) override - { - return qskInheritLocale( window, locale ); - } - - QLocale value( const QskControl* control ) const override - { - return control->locale(); - } - - QLocale value( const QskWindow* window ) const override - { - return window->locale(); - } - }; -} - class QskSetup::PrivateData { public: @@ -254,23 +216,6 @@ QskGraphicProvider* QskSetup::graphicProvider( const QString& providerId ) const return m_data->graphicProviders.provider( providerId ); } -QLocale QskSetup::inheritedLocale( const QObject* object ) -{ - VisitorLocale visitor; - visitor.setResolveValue( QLocale() ); - - QskObjectTree::traverseUp( const_cast< QObject* >( object ), visitor ); - return visitor.resolveValue(); -} - -void QskSetup::inheritLocale( QObject* object, const QLocale& locale ) -{ - VisitorLocale visitor; - visitor.setResolveValue( locale ); - - QskObjectTree::traverseDown( object, visitor ); -} - bool QskSetup::eventFilter( QObject* object, QEvent* event ) { if ( auto control = qskControlCast( object ) ) diff --git a/src/controls/QskSetup.h b/src/controls/QskSetup.h index 769ee6b1..81109718 100644 --- a/src/controls/QskSetup.h +++ b/src/controls/QskSetup.h @@ -16,8 +16,6 @@ class QskSkin; class QQuickItem; class QskGraphicProvider; -class QLocale; - #if defined( qskSetup ) #undef qskSetup #endif @@ -51,9 +49,6 @@ class QSK_EXPORT QskSetup : public QObject static void setup(); static void cleanup(); - QLocale inheritedLocale( const QObject* ); - void inheritLocale( QObject*, const QLocale& ); - static QskSetup* qmlAttachedProperties( QObject* ); Q_SIGNALS: diff --git a/src/controls/QskSkinHintTable.cpp b/src/controls/QskSkinHintTable.cpp index 7b654c65..4db0c557 100644 --- a/src/controls/QskSkinHintTable.cpp +++ b/src/controls/QskSkinHintTable.cpp @@ -14,7 +14,7 @@ inline const QVariant* qskResolvedHint( QskAspect aspect, const std::unordered_map< QskAspect, QVariant >& hints, QskAspect* resolvedAspect ) { - const auto a = aspect; + auto a = aspect; Q_FOREVER { @@ -56,6 +56,16 @@ inline const QVariant* qskResolvedHint( QskAspect aspect, continue; } + if ( aspect.section() != QskAspect::Body ) + { + // try to resolve from QskAspect::Body + + a.setSection( QskAspect::Body ); + aspect = a; + + continue; + } + return nullptr; } } diff --git a/src/controls/QskSkinnable.cpp b/src/controls/QskSkinnable.cpp index e3fad4ff..45ed2f8f 100644 --- a/src/controls/QskSkinnable.cpp +++ b/src/controls/QskSkinnable.cpp @@ -838,6 +838,9 @@ QVariant QskSkinnable::effectiveSkinHint( { aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) ); + if ( aspect.section() == QskAspect::Body ) + aspect.setSection( section() ); + if ( aspect.placement() == QskAspect::NoPlacement ) aspect.setPlacement( effectivePlacement() ); @@ -1337,6 +1340,11 @@ QskAspect::Placement QskSkinnable::effectivePlacement() const return QskAspect::NoPlacement; } +QskAspect::Section QskSkinnable::section() const +{ + return QskAspect::Body; +} + void QskSkinnable::updateNode( QSGNode* parentNode ) { effectiveSkinlet()->updateNode( this, parentNode ); diff --git a/src/controls/QskSkinnable.h b/src/controls/QskSkinnable.h index 98e65e6b..7a3345f6 100644 --- a/src/controls/QskSkinnable.h +++ b/src/controls/QskSkinnable.h @@ -103,6 +103,8 @@ class QSK_EXPORT QskSkinnable QVariant effectiveSkinHint( QskAspect, QskSkinHintStatus* = nullptr ) const; virtual QskAspect::Placement effectivePlacement() const; + virtual QskAspect::Section section() const; + QskSkinHintStatus hintStatus( QskAspect ) const; QRectF subControlRect( const QRectF&, QskAspect::Subcontrol ) const; diff --git a/src/controls/QskWindow.cpp b/src/controls/QskWindow.cpp index a49f5c48..e63cd663 100644 --- a/src/controls/QskWindow.cpp +++ b/src/controls/QskWindow.cpp @@ -34,6 +34,9 @@ Q_LOGGING_CATEGORY( logTiming, "qsk.window.timing", QtCriticalMsg ) #endif +extern QLocale qskInheritedLocale( const QObject* ); +extern void qskInheritLocale( QObject*, const QLocale& ); + static void qskResolveLocale( QskWindow* ); static bool qskEnforcedSkin = false; @@ -423,7 +426,7 @@ void QskWindow::setLocale( const QLocale& locale ) { d->locale = locale; qskSendEventTo( this, QEvent::LocaleChange ); - qskSetup->inheritLocale( this, locale ); + qskInheritLocale( this, locale ); } } @@ -452,14 +455,14 @@ static void qskResolveLocale( QskWindow* window ) { auto d = static_cast< QskWindowPrivate* >( QQuickWindowPrivate::get( window ) ); - const QLocale locale = qskSetup->inheritedLocale( window ); + const auto locale = qskInheritedLocale( window ); if ( d->locale != locale ) { d->locale = locale; qskSendEventTo( window, QEvent::LocaleChange ); - qskSetup->inheritLocale( window, locale ); + qskInheritLocale( window, locale ); } } diff --git a/src/graphic/QskGraphic.cpp b/src/graphic/QskGraphic.cpp index 7280c935..d2924e48 100644 --- a/src/graphic/QskGraphic.cpp +++ b/src/graphic/QskGraphic.cpp @@ -1068,6 +1068,21 @@ QskGraphic QskGraphic::fromPixmapAsImage( const QPixmap& pixmap ) return fromImage( pixmap.toImage() ); } +QskGraphic QskGraphic::fromGraphic( + const QskGraphic& graphic, const QskColorFilter& colorFilter ) +{ + if ( colorFilter.isIdentity() ) + return graphic; + + QskGraphic recoloredGraphic; + + QPainter painter( &recoloredGraphic ); + graphic.render( &painter, colorFilter ); + painter.end(); + + return recoloredGraphic; +} + #ifndef QT_NO_DEBUG_STREAM #include diff --git a/src/graphic/QskGraphic.h b/src/graphic/QskGraphic.h index ff27938f..29519e8b 100644 --- a/src/graphic/QskGraphic.h +++ b/src/graphic/QskGraphic.h @@ -125,6 +125,7 @@ class QSK_EXPORT QskGraphic : public QPaintDevice static QskGraphic fromImage( const QImage& ); static QskGraphic fromPixmap( const QPixmap& ); static QskGraphic fromPixmapAsImage( const QPixmap& ); + static QskGraphic fromGraphic( const QskGraphic&, const QskColorFilter& ); quint64 modificationId() const; QskHashValue hash( QskHashValue seed ) const; diff --git a/src/graphic/QskStandardSymbol.cpp b/src/graphic/QskStandardSymbol.cpp index 63212227..abddcae6 100644 --- a/src/graphic/QskStandardSymbol.cpp +++ b/src/graphic/QskStandardSymbol.cpp @@ -187,6 +187,25 @@ static void qskInformationGraphic( QPainter* painter ) painter->drawPath( path ); } +static void qskCheckMarkGraphic( QPainter* painter ) +{ + QPainterPath path; + + path.moveTo( 0.0, 0.5 ); + path.lineTo( 0.33, 1.0 ); + path.lineTo( 1.0, 0.0 ); + + painter->setPen( QPen( Qt::black, 0.2 ) ); + painter->drawPath( path ); +} + +static void qskCrossMarkGraphic( QPainter* painter ) +{ + painter->setPen( QPen( Qt::black, 0.2 ) ); + painter->drawLine( 0.0, 0.0, 1.0, 1.0 ); + painter->drawLine( 0.0, 1.0, 1.0, 0.0 ); +} + QskGraphic QskStandardSymbol::graphic( Type symbolType ) { static QskGraphic graphics[ SymbolTypeCount ]; @@ -227,11 +246,25 @@ QskGraphic QskStandardSymbol::graphic( Type symbolType ) break; } case QskStandardSymbol::Information: - default: { qskInformationGraphic( &painter ); break; } + case QskStandardSymbol::CheckMark: + { + qskCheckMarkGraphic( &painter ); + break; + } + case QskStandardSymbol::CrossMark: + { + qskCrossMarkGraphic( &painter ); + break; + } + case QskStandardSymbol::NoSymbol: + case QskStandardSymbol::SymbolTypeCount: + { + break; + } } } diff --git a/src/graphic/QskStandardSymbol.h b/src/graphic/QskStandardSymbol.h index dde16e18..385ec670 100644 --- a/src/graphic/QskStandardSymbol.h +++ b/src/graphic/QskStandardSymbol.h @@ -27,6 +27,9 @@ namespace QskStandardSymbol Critical, Question, + CheckMark, + CrossMark, + SymbolTypeCount }; diff --git a/src/layouts/QskLayoutChain.h b/src/layouts/QskLayoutChain.h index 88095cab..a834a5e6 100644 --- a/src/layouts/QskLayoutChain.h +++ b/src/layouts/QskLayoutChain.h @@ -39,12 +39,12 @@ class QskLayoutChain metrics.setMetric( which, size ); } - QskLayoutMetrics metrics; - int stretch = 0; bool canGrow = false; bool isShrunk = false; bool isValid = false; + + QskLayoutMetrics metrics; }; enum FillMode diff --git a/tests/checkboxes/checkboxes.pro b/tests/checkboxes/checkboxes.pro deleted file mode 100644 index 79376a0b..00000000 --- a/tests/checkboxes/checkboxes.pro +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG += qskexample - CONFIG += console - CONFIG += testcase - - QT += testlib - - HEADERS += \ - main.h - - SOURCES += \ - main.cpp diff --git a/tests/checkboxes/main.cpp b/tests/checkboxes/main.cpp deleted file mode 100644 index 711a9d4a..00000000 --- a/tests/checkboxes/main.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#include "main.h" - -#include - -void CheckBoxTests::init() -{ - root = new QskControl(); -} - -void CheckBoxTests::cleanup() -{ - delete root; -} - -void CheckBoxTests::checkbox() -{ - auto t = new QskCheckBox( root ); - - QVERIFY( t->isCheckable() ); -} - -void CheckBoxTests::click() -{ - auto t = new QskCheckBox( root ); - - QVERIFY( t->isChecked() == false ); - t->click(); - QVERIFY( t->isChecked() ); -} - -void CheckBoxTests::toggle() -{ - auto t = new QskCheckBox( root ); - - QVERIFY( t->isChecked() == false ); - t->toggle(); - QVERIFY( t->isChecked() ); - - t->toggle(); - QVERIFY( t->isChecked() == false ); -} - -void CheckBoxTests::tristate() -{ - auto t = new QskCheckBox( root ); - - QVERIFY( t->isChecked() == false ); - QVERIFY( t->isTristate() == false ); - - t->setCheckState( Qt::CheckState::PartiallyChecked ); - - QVERIFY( t->isChecked() == true ); - QVERIFY( t->isTristate() == true ); -} - -void CheckBoxTests::higherGroupUpdatesLower() -{ - auto t = new QskCheckBox( root ); - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - auto t3 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t2 ); - t->addToGroup( t3 ); - - QVERIFY( t->isChecked() == false ); - QVERIFY( t1->isChecked() == false ); - QVERIFY( t2->isChecked() == false ); - QVERIFY( t3->isChecked() == false ); - - t->setChecked( true ); - QVERIFY( t->isChecked() ); - QVERIFY( t1->isChecked() ); - QVERIFY( t2->isChecked() ); - QVERIFY( t3->isChecked() ); - - t->setChecked( false ); - QVERIFY( t->isChecked() == false ); - QVERIFY( t1->isChecked() == false ); - QVERIFY( t2->isChecked() == false ); - QVERIFY( t3->isChecked() == false ); - -} - -void CheckBoxTests::lowerGroupUpdatesHigher() -{ - auto t = new QskCheckBox( root ); - - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t2 ); - - t1->setChecked( true ); - QVERIFY( t->isChecked() ); - QVERIFY( t->isTristate() ); - QVERIFY( t->checkState() == Qt::CheckState::PartiallyChecked ); - QVERIFY( t1->isChecked() == true ); - QVERIFY( t2->isChecked() == false ); - - - t2->setChecked( true ); - QVERIFY( t->isChecked() ); - QVERIFY( t->isTristate() ); - QVERIFY( t->checkState() == Qt::CheckState::Checked ); - QVERIFY( t1->isChecked() == true ); - QVERIFY( t2->isChecked() == true ); - - t1->setChecked( false ); - QVERIFY( t->isChecked() ); - QVERIFY( t->isTristate() ); - QVERIFY( t->checkState() == Qt::CheckState::PartiallyChecked ); - QVERIFY( t1->isChecked() == false ); - QVERIFY( t2->isChecked() == true ); - - t2->setChecked( false ); - QVERIFY( t->isChecked() == false ); - QVERIFY( t->isTristate() ); - QVERIFY( t->checkState() == Qt::CheckState::Unchecked ); - QVERIFY( t1->isChecked() == false ); - QVERIFY( t2->isChecked() == false ); -} - -void CheckBoxTests::addToGroup() -{ - auto t = new QskCheckBox( root ); - - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t2 ); - - t->setChecked( true ); - QVERIFY( t->isChecked() ); - QVERIFY( t1->isChecked() ); - QVERIFY( t2->isChecked() ); - - auto t3 = new QskCheckBox( root ); - t->addToGroup( t3 ); - - QVERIFY( t->checkState() == Qt::CheckState::PartiallyChecked ); - - t3->setChecked( true ); - QVERIFY( t->checkState() == Qt::CheckState::Checked ); - auto t4 = new QskCheckBox( root ); - t4->setChecked( true ); - t->addToGroup( t4 ); - QVERIFY( t->checkState() == Qt::CheckState::Checked ); -} - -void CheckBoxTests::addPartlyToGroup() { - auto t = new QskCheckBox( root ); - - auto t1 = new QskCheckBox( root ); - auto t1a = new QskCheckBox( root ); - auto t1b = new QskCheckBox( root ); - - t1->addToGroup( t1a ); - t1->addToGroup( t1b ); - - t1a->setChecked( true ); - - QVERIFY( t1->checkState() == Qt::CheckState::PartiallyChecked ); - t->addToGroup( t1 ); - QVERIFY( t1->checkState() == Qt::CheckState::PartiallyChecked ); -} - -void CheckBoxTests::removeFromGroup() -{ - auto t = new QskCheckBox( root ); - - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t2 ); - - t2->setChecked( true ); - QVERIFY( t->checkState() == Qt::CheckState::PartiallyChecked ); - - t->removeFromGroup( t2 ); - QVERIFY( t->isChecked() == false ); -} - -void CheckBoxTests::groupMemberGetsDeleted() -{ - auto t = new QskCheckBox( root ); - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t2 ); - - t2->setChecked( true ); - QVERIFY( t->checkState() == Qt::CheckState::PartiallyChecked ); - - delete t2; - QVERIFY( t->isChecked() == false ); -} - -void CheckBoxTests::addTwiceToSameGroup() -{ - auto t = new QskCheckBox( root ); - - auto t1 = new QskCheckBox( root ); - auto t2 = new QskCheckBox( root ); - - t->addToGroup( t1 ); - t->addToGroup( t1 ); - t->removeFromGroup( t1 ); - - t->addToGroup( t2 ); - - t2->setChecked( true ); - - QVERIFY( t->checkState() == Qt::CheckState::Checked ); -} - -#include "moc_main.cpp" - diff --git a/tests/checkboxes/main.h b/tests/checkboxes/main.h deleted file mode 100644 index f657b6c8..00000000 --- a/tests/checkboxes/main.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -class QskControl; -class CheckBoxTests : public QObject -{ - Q_OBJECT - - QskControl * root; - private Q_SLOTS: - void init(); - void cleanup(); - - void checkbox(); - void click(); - void toggle(); - void tristate(); - void higherGroupUpdatesLower(); - void lowerGroupUpdatesHigher(); - void addToGroup(); - void addPartlyToGroup(); - void removeFromGroup(); - void groupMemberGetsDeleted(); - void addTwiceToSameGroup(); -}; - -QTEST_MAIN(CheckBoxTests) - diff --git a/tests/tests.pro b/tests/tests.pro deleted file mode 100644 index 60e10ea4..00000000 --- a/tests/tests.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += \ - checkboxes -