From f529fda278eaed768b8ced5e71cc7d3edf045d6b Mon Sep 17 00:00:00 2001 From: Clemens Manert Date: Mon, 4 Apr 2022 00:57:02 +0200 Subject: [PATCH] Add checkbox-groups --- src/controls/QskCheckBox.cpp | 94 +++++++++++++++++++++++++++++++++++- src/controls/QskCheckBox.h | 6 +++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/controls/QskCheckBox.cpp b/src/controls/QskCheckBox.cpp index 6789900f..7251db0a 100644 --- a/src/controls/QskCheckBox.cpp +++ b/src/controls/QskCheckBox.cpp @@ -11,6 +11,8 @@ QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 ) struct QskCheckBox::PrivateData { + QSet< QskAbstractButton* > group; + int groupItemsChecked; Qt::CheckState checkState; bool checkStateChanging : 1; bool toggleChanging : 1; @@ -18,8 +20,9 @@ struct QskCheckBox::PrivateData }; QskCheckBox::QskCheckBox( QQuickItem* parent ) - : Inherited( parent ), m_data( new PrivateData{ Qt::CheckState::Unchecked, - false, false, false } ) { + : Inherited( parent ) + , m_data( new PrivateData { QSet< QskAbstractButton* >(), 0, + Qt::Unchecked, false, false, false } ) { setAcceptHoverEvents( true ); initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); @@ -32,6 +35,7 @@ QskCheckBox::QskCheckBox( QQuickItem* parent ) QskCheckBox::~QskCheckBox() { + Q_EMIT removeFromAllGroupsRequested(); } bool QskCheckBox::isCheckable() const @@ -92,4 +96,90 @@ void QskCheckBox::setTriState( bool triState ) } } +void QskCheckBox::updated() +{ + if( m_data->toggleChanging ) + { + return; + } + + auto& groupItemsChecked = m_data->groupItemsChecked; + + if( groupItemsChecked == m_data->group.size() ) + { + this->setCheckState( Qt::CheckState::Checked ); + } + else if ( groupItemsChecked == 0 ) + { + this->setCheckState( Qt::CheckState::Unchecked ); + } + else + { + this->setCheckState( Qt::CheckState::PartiallyChecked ); + } +} + +void QskCheckBox::addToGroup( QskCheckBox* groupItem ) { + if( m_data->group.contains( groupItem ) ) + { + return; + } + + m_data->group.insert( groupItem ); + + if( groupItem->checkState() == Qt::CheckState::Checked ) + { + m_data->groupItemsChecked += 1; + } + + updated(); + + connect( this, &QskCheckBox::checkStateChanged, + groupItem, [ this, groupItem ] ( Qt::CheckState checkState ) + { + 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; + } + } ); + + connect( groupItem, &QskAbstractButton::toggled, + this, [ this, groupItem ] ( bool toggled ) + { + auto& groupItemsChecked = m_data->groupItemsChecked; + 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::CheckState::Checked ) + { + m_data->groupItemsChecked -= 1; + } + + updated(); +} + #include "moc_QskCheckBox.cpp" diff --git a/src/controls/QskCheckBox.h b/src/controls/QskCheckBox.h index 87f39e7a..eed70a7b 100644 --- a/src/controls/QskCheckBox.h +++ b/src/controls/QskCheckBox.h @@ -25,6 +25,9 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton bool isTriState() const; bool isCheckable() const override final; + void addToGroup( QskCheckBox* groupItem ); + void removeFromGroup( QskCheckBox* groupItem ); + public Q_SLOTS: void setCheckState( Qt::CheckState ); void setTriState( bool triState = true ); @@ -32,8 +35,11 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton Q_SIGNALS: void checkStateChanged( Qt::CheckState ); void isTriStateChanged( bool ); + void removeFromAllGroupsRequested(); + private: void setCheckStateInternal( Qt::CheckState ); + void updated(); struct PrivateData; std::unique_ptr< PrivateData > m_data;