Starting with a simpler version of QskCheckBox ( no tristate ), but with
having an optional text.
This commit is contained in:
parent
e67bc4a5ed
commit
cda5a8b45c
|
@ -86,15 +86,14 @@ namespace
|
||||||
CheckButtonBox( QQuickItem* parent = nullptr )
|
CheckButtonBox( QQuickItem* parent = nullptr )
|
||||||
: QskLinearBox( Qt::Horizontal, parent )
|
: QskLinearBox( Qt::Horizontal, parent )
|
||||||
{
|
{
|
||||||
setSpacing( 20 );
|
setSpacing( 40 );
|
||||||
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
|
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
|
||||||
|
|
||||||
for ( auto state : { Qt::Unchecked, Qt::PartiallyChecked, Qt::Checked } )
|
auto button1 = new QskCheckBox( "Options 1", this );
|
||||||
{
|
button1->setChecked( true );
|
||||||
auto button = new QskCheckBox( this );
|
|
||||||
button->setTristate( true );
|
auto button2 = new QskCheckBox( "Options 2", this );
|
||||||
button->setCheckState( state );
|
button2->setLayoutMirroring( true );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ SUBDIRS = \
|
||||||
qmlexport \
|
qmlexport \
|
||||||
tools \
|
tools \
|
||||||
support \
|
support \
|
||||||
tests \
|
|
||||||
examples \
|
examples \
|
||||||
playground
|
playground
|
||||||
|
|
||||||
|
|
|
@ -201,20 +201,27 @@ void Editor::setupCheckBox()
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
using Q = QskCheckBox;
|
using Q = QskCheckBox;
|
||||||
|
|
||||||
|
setSpacing( Q::Panel, 5 );
|
||||||
|
|
||||||
const qreal size = qskDpiScaled( 18 );
|
const qreal size = qskDpiScaled( 18 );
|
||||||
|
|
||||||
setStrutSize( Q::Panel, size, size );
|
setStrutSize( Q::Box, size, size );
|
||||||
setPadding( Q::Panel, 3 );
|
setPadding( Q::Box, 3 );
|
||||||
|
|
||||||
setBoxShape( Q::Panel, 2 );
|
setBoxShape( Q::Box, 2 );
|
||||||
|
|
||||||
setGradient( Q::Panel, m_pal.baseColor);
|
setGradient( Q::Box, m_pal.baseColor);
|
||||||
setGradient( Q::Panel | Q::Checked, m_pal.accentColor );
|
setGradient( Q::Box | Q::Checked, m_pal.accentColor );
|
||||||
setGradient( Q::Panel | Q::Checked | Q::Disabled, QskRgb::Grey );
|
setGradient( Q::Box | Q::Disabled, QskRgb::Grey );
|
||||||
|
|
||||||
setColor( Q::Indicator, m_pal.contrastColor );
|
setColor( Q::Indicator, m_pal.contrastColor );
|
||||||
|
|
||||||
setAnimation( Q::Panel | A::Color, qskDuration );
|
setColor( Q::Text, m_pal.textColor );
|
||||||
|
setColor( Q::Text | Q::Disabled, qskShadedColor( m_pal.textColor, 0.6 ) );
|
||||||
|
setFontRole( Q::Text, ButtonFontRole );
|
||||||
|
|
||||||
|
setAnimation( Q::Box | A::Color, qskDuration );
|
||||||
|
setAnimation( Q::Text | A::Color, qskDuration );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupBox()
|
void Editor::setupBox()
|
||||||
|
|
|
@ -305,19 +305,28 @@ void Editor::setupCheckBox()
|
||||||
|
|
||||||
const qreal size = qskDpiScaled( 26 );
|
const qreal size = qskDpiScaled( 26 );
|
||||||
|
|
||||||
setStrutSize( Q::Panel, size, size );
|
setSpacing( Q::Panel, qskDpiScaled( 5 ) );
|
||||||
|
|
||||||
setPadding( Q::Panel, qskDpiScaled( 5 ) );
|
setStrutSize( Q::Box, size, size );
|
||||||
setBoxShape( Q::Panel, qskDpiScaled( 3 ) );
|
|
||||||
setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) );
|
|
||||||
|
|
||||||
setBoxBorderColors( Q::Panel, m_pal.darker125 );
|
setPadding( Q::Box, qskDpiScaled( 5 ) );
|
||||||
setGradient( Q::Panel, m_pal.lighter135 );
|
setBoxShape( Q::Box, qskDpiScaled( 3 ) );
|
||||||
setGradient( Q::Panel | Q::Checked, m_pal.highlighted );
|
setBoxBorderMetrics( Q::Box, qskDpiScaled( 1 ) );
|
||||||
|
|
||||||
|
setBoxBorderColors( Q::Box, m_pal.darker125 );
|
||||||
|
setGradient( Q::Box, m_pal.lighter135 );
|
||||||
|
setGradient( Q::Box | Q::Checked, m_pal.highlighted );
|
||||||
|
|
||||||
|
setGradient( Q::Box | Q::Disabled, m_pal.lighter110 );
|
||||||
|
setBoxBorderColors( Q::Box, m_pal.theme );
|
||||||
|
|
||||||
setColor( Q::Indicator, m_pal.lighter135 );
|
setColor( Q::Indicator, m_pal.lighter135 );
|
||||||
|
|
||||||
setAnimation( Q::Panel | A::Color, qskDuration );
|
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()
|
void Editor::setupPopup()
|
||||||
|
|
|
@ -4,50 +4,37 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskCheckBox.h"
|
#include "QskCheckBox.h"
|
||||||
#include "QskAspect.h"
|
|
||||||
|
|
||||||
#include <qset.h>
|
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskCheckBox, Panel )
|
QSK_SUBCONTROL( QskCheckBox, Panel )
|
||||||
|
QSK_SUBCONTROL( QskCheckBox, Box )
|
||||||
QSK_SUBCONTROL( QskCheckBox, Indicator )
|
QSK_SUBCONTROL( QskCheckBox, Indicator )
|
||||||
|
QSK_SUBCONTROL( QskCheckBox, Text )
|
||||||
QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 )
|
|
||||||
|
|
||||||
class QskCheckBox::PrivateData
|
class QskCheckBox::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrivateData()
|
PrivateData( const QString& text )
|
||||||
: checkState( Qt::Unchecked )
|
: text( text )
|
||||||
, checkStateChanging( false )
|
|
||||||
, toggleChanging( false )
|
|
||||||
, tristate( false )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet< QskAbstractButton* > group;
|
QString text;
|
||||||
|
|
||||||
int groupItemsChecked = 0;
|
|
||||||
|
|
||||||
Qt::CheckState checkState : 2;
|
|
||||||
bool checkStateChanging : 1;
|
|
||||||
bool toggleChanging : 1;
|
|
||||||
bool tristate : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskCheckBox::QskCheckBox( QQuickItem* parent )
|
QskCheckBox::QskCheckBox( QQuickItem* parent )
|
||||||
: Inherited( parent )
|
: QskCheckBox( QString(), parent )
|
||||||
, m_data( new PrivateData() )
|
|
||||||
{
|
{
|
||||||
setAcceptHoverEvents( true );
|
}
|
||||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
|
||||||
|
|
||||||
connect( this, &QskCheckBox::checkedChanged, this,
|
QskCheckBox::QskCheckBox( const QString& text, QQuickItem* parent )
|
||||||
[ this ]( bool on ) { setCheckStateInternal( on ? Qt::Checked : Qt::Unchecked ); } );
|
: Inherited( parent )
|
||||||
|
, m_data( new PrivateData( text ) )
|
||||||
|
{
|
||||||
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskCheckBox::~QskCheckBox()
|
QskCheckBox::~QskCheckBox()
|
||||||
{
|
{
|
||||||
Q_EMIT removeFromAllGroupsRequested();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QskCheckBox::isCheckable() const
|
bool QskCheckBox::isCheckable() const
|
||||||
|
@ -55,130 +42,33 @@ bool QskCheckBox::isCheckable() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::CheckState QskCheckBox::checkState() const
|
void QskCheckBox::setText( const QString& text )
|
||||||
{
|
{
|
||||||
return m_data->checkState;
|
if ( text != m_data->text )
|
||||||
}
|
|
||||||
|
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
setChecked( true );
|
m_data->text = text;
|
||||||
setTristate( true );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setChecked( checkState == Qt::Checked );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data->checkStateChanging = false;
|
resetImplicitSize();
|
||||||
|
update();
|
||||||
|
|
||||||
setCheckStateInternal( checkState );
|
Q_EMIT textChanged();
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskCheckBox::updated()
|
QString QskCheckBox::text() const
|
||||||
{
|
{
|
||||||
if( m_data->toggleChanging )
|
return m_data->text;
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskCheckBox::addToGroup( QskCheckBox* groupItem )
|
void QskCheckBox::changeEvent( QEvent* event )
|
||||||
{
|
{
|
||||||
if( m_data->group.contains( groupItem ) )
|
if ( event->type() == QEvent::LayoutDirectionChange )
|
||||||
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( checkState == Qt::Checked )
|
if ( !m_data->text.isEmpty() )
|
||||||
{
|
update();
|
||||||
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,
|
Inherited::changeEvent( event );
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskCheckBox.cpp"
|
#include "moc_QskCheckBox.cpp"
|
||||||
|
|
|
@ -12,41 +12,32 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY( Qt::CheckState checkState READ checkState
|
Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged FINAL )
|
||||||
WRITE setCheckState NOTIFY checkStateChanged FINAL )
|
|
||||||
|
|
||||||
Q_PROPERTY( bool tristate READ isTristate
|
|
||||||
WRITE setTristate NOTIFY tristateChanged FINAL )
|
|
||||||
|
|
||||||
using Inherited = QskAbstractButton;
|
using Inherited = QskAbstractButton;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Panel, Indicator )
|
QSK_SUBCONTROLS( Panel, Box, Indicator, Text )
|
||||||
QSK_STATES( PartiallyChecked )
|
|
||||||
|
|
||||||
QskCheckBox( QQuickItem* parent = nullptr );
|
QskCheckBox( QQuickItem* parent = nullptr );
|
||||||
|
QskCheckBox( const QString&, QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
~QskCheckBox() override;
|
~QskCheckBox() override;
|
||||||
|
|
||||||
Qt::CheckState checkState() const;
|
QString text() const;
|
||||||
bool isTristate() const;
|
|
||||||
bool isCheckable() const override final;
|
bool isCheckable() const override final;
|
||||||
|
|
||||||
void addToGroup( QskCheckBox* );
|
|
||||||
void removeFromGroup( QskCheckBox* );
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setCheckState( Qt::CheckState );
|
void setText( const QString& );
|
||||||
void setTristate( bool triState = true );
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void checkStateChanged( Qt::CheckState );
|
void textChanged();
|
||||||
void tristateChanged( bool );
|
|
||||||
void removeFromAllGroupsRequested();
|
protected:
|
||||||
|
void changeEvent( QEvent* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setCheckStateInternal( Qt::CheckState );
|
|
||||||
void updated();
|
|
||||||
|
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "QskCheckBoxSkinlet.h"
|
#include "QskCheckBoxSkinlet.h"
|
||||||
#include "QskCheckBox.h"
|
#include "QskCheckBox.h"
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
|
#include "QskTextOptions.h"
|
||||||
|
#include "QskFunctions.h"
|
||||||
|
|
||||||
#include <QSGFlatColorMaterial>
|
#include <QSGFlatColorMaterial>
|
||||||
#include <qsgnode.h>
|
#include <qsgnode.h>
|
||||||
|
@ -25,7 +27,7 @@ namespace
|
||||||
setMaterial( &m_material );
|
setMaterial( &m_material );
|
||||||
}
|
}
|
||||||
|
|
||||||
void update( bool isPartially, const QRectF& rect, const QColor& color )
|
void update( const QRectF& rect, const QColor& color )
|
||||||
{
|
{
|
||||||
if ( color != m_material.color() )
|
if ( color != m_material.color() )
|
||||||
{
|
{
|
||||||
|
@ -33,10 +35,9 @@ namespace
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rect != m_rect || isPartially != m_isPartially )
|
if ( rect != m_rect )
|
||||||
{
|
{
|
||||||
m_rect = rect;
|
m_rect = rect;
|
||||||
m_isPartially = isPartially;
|
|
||||||
|
|
||||||
const auto x = rect.x();
|
const auto x = rect.x();
|
||||||
const auto y = rect.y();
|
const auto y = rect.y();
|
||||||
|
@ -45,18 +46,9 @@ namespace
|
||||||
|
|
||||||
auto points = m_geometry.vertexDataAsPoint2D();
|
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[0].set( x, y + h / 2 );
|
||||||
points[1].set( x + w / 3, y + h );
|
points[1].set( x + w / 3, y + h );
|
||||||
points[2].set( x + w, y );
|
points[2].set( x + w, y );
|
||||||
}
|
|
||||||
|
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
}
|
}
|
||||||
|
@ -67,14 +59,13 @@ namespace
|
||||||
QSGGeometry m_geometry;
|
QSGGeometry m_geometry;
|
||||||
|
|
||||||
QRectF m_rect;
|
QRectF m_rect;
|
||||||
bool m_isPartially;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
|
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
|
||||||
: QskSkinlet( skin )
|
: QskSkinlet( skin )
|
||||||
{
|
{
|
||||||
setNodeRoles( { PanelRole, IndicatorRole } );
|
setNodeRoles( { BoxRole, IndicatorRole, TextRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
|
QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
|
||||||
|
@ -84,12 +75,66 @@ QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
|
||||||
QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
if ( subControl == QskCheckBox::Indicator )
|
const auto checkBox = static_cast< const QskCheckBox* >( skinnable );
|
||||||
return skinnable->innerBox( QskCheckBox::Panel, contentsRect );
|
|
||||||
|
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;
|
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(
|
QSGNode* QskCheckBoxSkinlet::updateSubNode(
|
||||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
|
@ -100,8 +145,14 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode(
|
||||||
case PanelRole:
|
case PanelRole:
|
||||||
return updateBoxNode( skinnable, node, QskCheckBox::Panel );
|
return updateBoxNode( skinnable, node, QskCheckBox::Panel );
|
||||||
|
|
||||||
|
case BoxRole:
|
||||||
|
return updateBoxNode( skinnable, node, QskCheckBox::Box );
|
||||||
|
|
||||||
case IndicatorRole:
|
case IndicatorRole:
|
||||||
return updateIndicatorNode( checkBox, node );
|
return updateIndicatorNode( checkBox, node );
|
||||||
|
|
||||||
|
case TextRole:
|
||||||
|
return updateTextNode( checkBox, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
@ -112,8 +163,7 @@ QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
|
||||||
{
|
{
|
||||||
using Q = QskCheckBox;
|
using Q = QskCheckBox;
|
||||||
|
|
||||||
const auto state = checkBox->checkState();
|
if ( !checkBox->isChecked() )
|
||||||
if ( state == Qt::Unchecked )
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto rect = checkBox->subControlRect( Q::Indicator );
|
const auto rect = checkBox->subControlRect( Q::Indicator );
|
||||||
|
@ -121,15 +171,54 @@ QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node );
|
auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node );
|
||||||
indicatorNode->update( state != Qt::Checked, rect, checkBox->color( Q::Indicator ) );
|
indicatorNode->update( rect, checkBox->color( Q::Indicator ) );
|
||||||
|
|
||||||
return indicatorNode;
|
return indicatorNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSGNode* QskCheckBoxSkinlet::updateTextNode(
|
||||||
Qt::SizeHint, const QSizeF& ) const
|
const QskCheckBox* checkBox, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
return skinnable->strutSizeHint( QskCheckBox::Panel );
|
using Q = QskCheckBox;
|
||||||
|
|
||||||
|
const auto rect = checkBox->subControlRect( Q::Text );
|
||||||
|
const auto alignH = checkBox->layoutMirroring() ? Qt::AlignRight : Qt::AlignLeft;
|
||||||
|
|
||||||
|
QskTextOptions textOptions;
|
||||||
|
textOptions.setElideMode( Qt::ElideMiddle );
|
||||||
|
|
||||||
|
return QskSkinlet::updateTextNode( checkBox, node, rect, alignH | Qt::AlignVCenter,
|
||||||
|
checkBox->text(), textOptions, QskCheckBox::Text );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
|
Qt::SizeHint which, const QSizeF& ) const
|
||||||
|
{
|
||||||
|
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"
|
#include "moc_QskCheckBoxSkinlet.cpp"
|
||||||
|
|
|
@ -20,7 +20,9 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
|
||||||
enum NodeRole
|
enum NodeRole
|
||||||
{
|
{
|
||||||
PanelRole,
|
PanelRole,
|
||||||
|
BoxRole,
|
||||||
IndicatorRole,
|
IndicatorRole,
|
||||||
|
TextRole,
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
@ -38,8 +40,12 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
virtual QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const;
|
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
|
#endif
|
||||||
|
|
|
@ -203,7 +203,7 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
|
|
||||||
QSizeF size( 0, 0 );
|
QSizeF size( 0, 0 );
|
||||||
|
|
||||||
const QFontMetricsF fm( button->font() );
|
const QFontMetricsF fm( button->effectiveFont( QskPushButton::Text ) );
|
||||||
|
|
||||||
if ( !button->text().isEmpty() )
|
if ( !button->text().isEmpty() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
CONFIG += qskexample
|
|
||||||
CONFIG += console
|
|
||||||
CONFIG += testcase
|
|
||||||
|
|
||||||
QT += testlib
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
main.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
main.cpp
|
|
|
@ -1,223 +0,0 @@
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#include <QskCheckBox.h>
|
|
||||||
|
|
||||||
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"
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <QtTest/QtTest>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
TEMPLATE = subdirs
|
|
||||||
|
|
||||||
SUBDIRS += \
|
|
||||||
checkboxes
|
|
||||||
|
|
Loading…
Reference in New Issue