formal cheges, check box added to gallery

This commit is contained in:
Uwe Rathmann 2022-04-04 14:14:07 +02:00
parent a05d1e3471
commit 49cdc1a029
5 changed files with 203 additions and 133 deletions

View File

@ -7,6 +7,7 @@
#include <QskSwitchButton.h> #include <QskSwitchButton.h>
#include <QskPushButton.h> #include <QskPushButton.h>
#include <QskCheckBox.h>
#include <QskSeparator.h> #include <QskSeparator.h>
#include <QskLinearBox.h> #include <QskLinearBox.h>
@ -78,6 +79,24 @@ namespace
} }
} }
}; };
class CheckButtonBox : public QskLinearBox
{
public:
CheckButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setSpacing( 20 );
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 );
}
}
};
} }
ButtonPage::ButtonPage( QQuickItem* parent ) ButtonPage::ButtonPage( QQuickItem* parent )
@ -92,4 +111,6 @@ void ButtonPage::populate()
new ButtonBox( this ); new ButtonBox( this );
new QskSeparator( Qt::Horizontal, this ); new QskSeparator( Qt::Horizontal, this );
new SwitchButtonBox( this ); new SwitchButtonBox( this );
new QskSeparator( Qt::Horizontal, this );
new CheckButtonBox( this );
} }

View File

@ -1,5 +1,9 @@
#include "QskCheckBox.h" /******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskCheckBox.h"
#include "QskAspect.h" #include "QskAspect.h"
#include <qset.h> #include <qset.h>
@ -9,11 +13,22 @@ QSK_SUBCONTROL( QskCheckBox, Tick )
QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 ) QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 )
struct QskCheckBox::PrivateData class QskCheckBox::PrivateData
{ {
public:
PrivateData()
: checkState( Qt::Unchecked )
, checkStateChanging( false )
, toggleChanging( false )
, triState( false )
{
}
QSet< QskAbstractButton* > group; QSet< QskAbstractButton* > group;
int groupItemsChecked;
Qt::CheckState checkState; int groupItemsChecked = 0;
int checkState : 2;
bool checkStateChanging : 1; bool checkStateChanging : 1;
bool toggleChanging : 1; bool toggleChanging : 1;
bool triState : 1; bool triState : 1;
@ -21,16 +36,13 @@ struct QskCheckBox::PrivateData
QskCheckBox::QskCheckBox( QQuickItem* parent ) QskCheckBox::QskCheckBox( QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData { QSet< QskAbstractButton* >(), 0, , m_data( new PrivateData() )
Qt::Unchecked, false, false, false } ) { {
setAcceptHoverEvents( true ); setAcceptHoverEvents( true );
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
connect( this, &QskCheckBox::checkedChanged, this, [ this ]( bool t ) connect( this, &QskCheckBox::checkedChanged, this,
{ [ this ]( bool on ) { setCheckStateInternal( on ? Qt::Checked : Qt::Unchecked ); } );
setCheckStateInternal( t ? Qt::CheckState::Checked :
Qt::CheckState::Unchecked );
} );
} }
QskCheckBox::~QskCheckBox() QskCheckBox::~QskCheckBox()
@ -45,18 +57,15 @@ bool QskCheckBox::isCheckable() const
Qt::CheckState QskCheckBox::checkState() const Qt::CheckState QskCheckBox::checkState() const
{ {
return m_data->checkState; return static_cast< Qt::CheckState >( m_data->checkState );
} }
void QskCheckBox::setCheckStateInternal( Qt::CheckState checkState ) void QskCheckBox::setCheckStateInternal( Qt::CheckState checkState )
{ {
if( m_data->checkStateChanging ) if( m_data->checkStateChanging )
{
return; return;
}
setSkinStateFlag( PartiallyChecked, setSkinStateFlag( PartiallyChecked, checkState == Qt::PartiallyChecked );
checkState == Qt::CheckState::PartiallyChecked );
m_data->checkState = checkState; m_data->checkState = checkState;
Q_EMIT checkStateChanged( checkState ); Q_EMIT checkStateChanged( checkState );
@ -68,15 +77,17 @@ void QskCheckBox::setCheckState( Qt::CheckState checkState )
return; return;
m_data->checkStateChanging = true; m_data->checkStateChanging = true;
if( checkState == Qt::CheckState::PartiallyChecked )
if( checkState == Qt::PartiallyChecked )
{ {
setChecked( true ); setChecked( true );
setTriState( true ); setTriState( true );
} }
else else
{ {
setChecked( checkState == Qt::CheckState::Checked ); setChecked( checkState == Qt::Checked );
} }
m_data->checkStateChanging = false; m_data->checkStateChanging = false;
setCheckStateInternal( checkState ); setCheckStateInternal( checkState );
@ -99,43 +110,38 @@ void QskCheckBox::setTriState( bool triState )
void QskCheckBox::updated() void QskCheckBox::updated()
{ {
if( m_data->toggleChanging ) if( m_data->toggleChanging )
{
return; return;
}
auto& groupItemsChecked = m_data->groupItemsChecked; const auto& groupItemsChecked = m_data->groupItemsChecked;
if( groupItemsChecked == m_data->group.size() ) if( groupItemsChecked == m_data->group.size() )
{ {
this->setCheckState( Qt::CheckState::Checked ); setCheckState( Qt::Checked );
} }
else if ( groupItemsChecked == 0 ) else if ( groupItemsChecked == 0 )
{ {
this->setCheckState( Qt::CheckState::Unchecked ); setCheckState( Qt::Unchecked );
} }
else else
{ {
this->setCheckState( Qt::CheckState::PartiallyChecked ); setCheckState( Qt::PartiallyChecked );
} }
} }
void QskCheckBox::addToGroup( QskCheckBox* groupItem ) { void QskCheckBox::addToGroup( QskCheckBox* groupItem )
{
if( m_data->group.contains( groupItem ) ) if( m_data->group.contains( groupItem ) )
{
return; return;
}
m_data->group.insert( groupItem ); m_data->group.insert( groupItem );
if( groupItem->checkState() == Qt::CheckState::Checked ) if( groupItem->checkState() == Qt::Checked )
{ m_data->groupItemsChecked++;
m_data->groupItemsChecked += 1;
}
updated(); updated();
connect( this, &QskCheckBox::checkStateChanged, connect( this, &QskCheckBox::checkStateChanged,
groupItem, [ this, groupItem ] ( Qt::CheckState checkState ) groupItem, [ this, groupItem ]( Qt::CheckState checkState )
{ {
if( checkState == Qt::Checked ) if( checkState == Qt::Checked )
{ {
@ -154,7 +160,7 @@ void QskCheckBox::addToGroup( QskCheckBox* groupItem ) {
} ); } );
connect( groupItem, &QskAbstractButton::toggled, connect( groupItem, &QskAbstractButton::toggled,
this, [ this, groupItem ] ( bool toggled ) this, [ this, groupItem ]( bool toggled )
{ {
auto& groupItemsChecked = m_data->groupItemsChecked; auto& groupItemsChecked = m_data->groupItemsChecked;
groupItemsChecked += toggled ? 1 : -1; groupItemsChecked += toggled ? 1 : -1;
@ -162,22 +168,16 @@ void QskCheckBox::addToGroup( QskCheckBox* groupItem ) {
} ); } );
connect( groupItem, &QskCheckBox::removeFromAllGroupsRequested, connect( groupItem, &QskCheckBox::removeFromAllGroupsRequested,
this, [ this, groupItem ] ( ) this, [ this, groupItem ]( ) { removeFromGroup( groupItem ); } );
{
removeFromGroup( groupItem );
} );
} }
void QskCheckBox::removeFromGroup( QskCheckBox* groupItem ) { void QskCheckBox::removeFromGroup( QskCheckBox* groupItem )
{
if( !m_data->group.remove( groupItem ) ) if( !m_data->group.remove( groupItem ) )
{
return; return;
}
if( groupItem->checkState() == Qt::CheckState::Checked ) if( groupItem->checkState() == Qt::Checked )
{ m_data->groupItemsChecked--;
m_data->groupItemsChecked -= 1;
}
updated(); updated();
} }

View File

@ -1,3 +1,8 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_CHECK_BOX_H #ifndef QSK_CHECK_BOX_H
#define QSK_CHECK_BOX_H #define QSK_CHECK_BOX_H
@ -9,6 +14,7 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton
Q_PROPERTY( Qt::CheckState checkState READ checkState Q_PROPERTY( Qt::CheckState checkState READ checkState
WRITE setCheckState NOTIFY checkStateChanged FINAL ) WRITE setCheckState NOTIFY checkStateChanged FINAL )
Q_PROPERTY( bool isTriState READ isTriState Q_PROPERTY( bool isTriState READ isTriState
WRITE setTriState NOTIFY isTriStateChanged FINAL ) WRITE setTriState NOTIFY isTriStateChanged FINAL )
@ -41,8 +47,8 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton
void setCheckStateInternal( Qt::CheckState ); void setCheckStateInternal( Qt::CheckState );
void updated(); void updated();
struct PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };
#endif // QSK_CHECK_BOX_H #endif

View File

@ -1,67 +1,88 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskCheckBoxSkinlet.h" #include "QskCheckBoxSkinlet.h"
#include "QskCheckBox.h" #include "QskCheckBox.h"
#include <QSGFlatColorMaterial> #include <QSGFlatColorMaterial>
#include <qsgnode.h> #include <qsgnode.h>
class Tic : public QSGGeometryNode { namespace
QSGFlatColorMaterial material; {
QSGGeometry geometry = QSGGeometry( class Tick : public QSGGeometryNode
QSGGeometry::defaultAttributes_Point2D(), 3 ); {
const QRectF& target; public:
public: Tick( const QRectF& rect, const QColor& color )
Tic( const QRectF& rect, const QColor& color ): target( rect ) { : m_target( rect )
geometry.setDrawingMode( QSGGeometry::DrawLineStrip ); , geometry( QSGGeometry::defaultAttributes_Point2D(), 3 )
geometry.setLineWidth( 2 ); {
setGeometry( &geometry ); geometry.setDrawingMode( QSGGeometry::DrawLineStrip );
geometry.setLineWidth( 2 );
setGeometry( &geometry );
material.setColor( color ); material.setColor( color );
setMaterial( &material ); setMaterial( &material );
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
} }
void setColor( const QColor& color ) { void setColor( const QColor& color ) {
material.setColor( color ); material.setColor( color );
markDirty( QSGNode::DirtyMaterial ); markDirty( QSGNode::DirtyMaterial );
} }
void makeTic() { void makeTick()
const auto& size = target.size(); {
const auto x = target.x(); const auto x = m_target.x();
const auto y = target.y(); const auto y = m_target.y();
geometry.vertexDataAsPoint2D()[0].set( x, y + size.height() / 2 ); auto vertexData = geometry.vertexDataAsPoint2D();
geometry.vertexDataAsPoint2D()[1].set( x + size.width() / 3,
y + size.height() );
geometry.vertexDataAsPoint2D()[2].set( x + size.width(), y );
markDirty( QSGNode::DirtyGeometry );
}
void makePartially() { vertexData[0].set( x, y + m_target.height() / 2 );
const auto& size = target.size(); vertexData[1].set( x + m_target.width() / 3, y + m_target.height() );
const auto x = target.x(); vertexData[2].set( x + m_target.width(), y );
const auto y = target.y();
geometry.vertexDataAsPoint2D()[0].set( x, y + size.height() / 2 ); markDirty( QSGNode::DirtyGeometry );
geometry.vertexDataAsPoint2D()[1].set( x, y + size.height() / 2 ); }
geometry.vertexDataAsPoint2D()[2].set( x + size.width(),
y + size.height() / 2 );
markDirty( QSGNode::DirtyGeometry ); void makePartially()
} {
const auto x = m_target.x();
const auto y = m_target.y();
void makeEmpty() { auto vertexData = geometry.vertexDataAsPoint2D();
const auto x = target.x();
const auto y = target.y();
geometry.vertexDataAsPoint2D()[0].set( x, y ); vertexData[0].set( x, y + m_target.height() / 2 );
geometry.vertexDataAsPoint2D()[1].set( x, y ); vertexData[1].set( x, y + m_target.height() / 2 );
geometry.vertexDataAsPoint2D()[2].set( x, y ); vertexData[2].set( x + m_target.width(), y + m_target.height() / 2 );
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
} }
};
void makeEmpty()
{
const auto x = m_target.x();
const auto y = m_target.y();
auto vertexData = geometry.vertexDataAsPoint2D();
vertexData[0].set( x, y );
vertexData[1].set( x, y );
vertexData[2].set( x, y );
markDirty( QSGNode::DirtyGeometry );
}
private:
const QRectF m_target;
QSGFlatColorMaterial material;
QSGGeometry geometry;
};
}
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin ) QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
: QskSkinlet( skin ) : QskSkinlet( skin )
@ -74,9 +95,7 @@ QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
} }
QRectF QskCheckBoxSkinlet::subControlRect( QRectF QskCheckBoxSkinlet::subControlRect(
const QskSkinnable*, const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const
const QRectF& contentsRect,
QskAspect::Subcontrol ) const
{ {
return contentsRect; return contentsRect;
} }
@ -84,49 +103,62 @@ QRectF QskCheckBoxSkinlet::subControlRect(
QSGNode* QskCheckBoxSkinlet::updateSubNode( QSGNode* QskCheckBoxSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{ {
switch( nodeRole ) { switch( nodeRole )
{
case BoxRole: case BoxRole:
return updateBoxNode( skinnable, node, {
QskCheckBox::Box ); return updateBoxNode( skinnable, node, QskCheckBox::Box );
}
case TickRole: case TickRole:
auto control = dynamic_cast< const QskCheckBox* >( skinnable ); {
auto rect = control->subControlRect( QskCheckBox::Tick ); auto checkBox = static_cast< const QskCheckBox* >( skinnable );
rect = rect.marginsRemoved( return updateTickNode( checkBox, node );
skinnable->marginHint( QskCheckBox::Tick ) ); }
Tic* tic;
if ( static_cast< Tic* >( node ) == nullptr )
{
tic = new Tic( rect, skinnable->color( QskCheckBox::Tick ) );
}
else
{
tic = static_cast< Tic* >( node );
}
switch ( control->checkState() ) {
case Qt::CheckState::Unchecked:
tic->setColor( skinnable->color( QskCheckBox::Tick ) );
tic->makeEmpty();
break;
case Qt::CheckState::PartiallyChecked:
tic->setColor( skinnable->color(
QskCheckBox::Tick | QskCheckBox::PartiallyChecked ) );
tic->makePartially();
break;
case Qt::CheckState::Checked:
tic->setColor( skinnable->color(
QskCheckBox::Tick | QskCheckBox::Checked ) );
tic->makeTic();
break;
}
return tic;
} }
return Inherited::updateSubNode( skinnable, nodeRole, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );
} }
QSGNode* QskCheckBoxSkinlet::updateTickNode(
const QskCheckBox* checkBox, QSGNode* node ) const
{
using Q = QskCheckBox;
auto rect = checkBox->subControlRect( Q::Tick );
rect = rect.marginsRemoved( checkBox->marginHint( Q::Tick ) );
auto tick = static_cast< Tick* >( node );
if ( tick == nullptr )
tick = new Tick( rect, checkBox->color( Q::Tick ) );
switch ( checkBox->checkState() )
{
case Qt::Unchecked:
tick->setColor( checkBox->color( Q::Tick ) );
tick->makeEmpty();
break;
case Qt::PartiallyChecked:
tick->setColor( checkBox->color( Q::Tick | Q::PartiallyChecked ) );
tick->makePartially();
break;
case Qt::Checked:
tick->setColor( checkBox->color( Q::Tick | Q::Checked ) );
tick->makeTick();
break;
}
return tick;
}
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable, QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint, const QSizeF& ) const Qt::SizeHint, const QSizeF& ) const
{ {

View File

@ -1,13 +1,21 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_CHECK_BOX_SKINLET_H #ifndef QSK_CHECK_BOX_SKINLET_H
#define QSK_CHECK_BOX_SKINLET_H #define QSK_CHECK_BOX_SKINLET_H
#include "QskSkinlet.h" #include "QskSkinlet.h"
class QskCheckBox;
class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
{ {
Q_GADGET Q_GADGET
using Inherited = QskSkinlet; using Inherited = QskSkinlet;
public: public:
enum NodeRole enum NodeRole
{ {
@ -27,6 +35,9 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
protected: protected:
QSGNode* updateSubNode( const QskSkinnable*, QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override; quint8 nodeRole, QSGNode* ) const override;
private:
QSGNode* updateTickNode( const QskCheckBox*, QSGNode* ) const;
}; };
#endif // QSK_CHECK_BOX_SKINLET_H #endif