QskSkinHintTableEditor: add overloads for all states
... also, remove part of the logic when looking up current states.
This commit is contained in:
parent
279ec9537c
commit
b49305248a
|
@ -8,7 +8,8 @@ SUBDIRS = \
|
|||
tools \
|
||||
support \
|
||||
examples \
|
||||
playground
|
||||
playground \
|
||||
tests
|
||||
|
||||
OTHER_FILES = \
|
||||
doc/Doxyfile \
|
||||
|
@ -24,3 +25,4 @@ skins.depends = src
|
|||
support.depends = src skins
|
||||
examples.depends = tools support skins qmlexport
|
||||
playground.depends = tools support skins qmlexport
|
||||
tests.depends = src
|
||||
|
|
|
@ -27,9 +27,9 @@ inline const QVariant* qskResolvedHint( QskAspect aspect,
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
if ( const auto topState = aspect.topState() )
|
||||
if ( aspect.hasState() )
|
||||
{
|
||||
aspect.clearState( topState );
|
||||
aspect.clearStates();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "QskBoxBorderColors.h"
|
||||
#include "QskGradient.h"
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline QskAspect aspectStrutSize( QskAspect aspect )
|
||||
|
@ -75,6 +77,31 @@ QskSkinHintTable* QskSkinHintTableEditor::table() const
|
|||
return m_table;
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setHint( QskAspect aspect, const QVariant& hint, QskAspect::State state )
|
||||
{
|
||||
forAllCombinationsSetHint( state, aspect, hint );
|
||||
}
|
||||
|
||||
bool QskSkinHintTableEditor::removeHint( QskAspect aspect, QskAspect::State state )
|
||||
{
|
||||
return forAllCombinationsRemoveHint( state, aspect );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setFlagHint( QskAspect aspect, const QVariant& hint, QskAspect::State state )
|
||||
{
|
||||
setHint( aspect | QskAspect::Flag, hint, state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setMetricHint( QskAspect aspect, const QVariant& hint, QskAspect::State state )
|
||||
{
|
||||
setHint( aspect | QskAspect::Metric, hint, state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setColorHint( QskAspect aspect, const QVariant& hint, QskAspect::State state )
|
||||
{
|
||||
setHint( aspect | QskAspect::Color, hint, state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setFlag( QskAspect aspect, int flag )
|
||||
{
|
||||
setFlagHint( aspect, flag );
|
||||
|
@ -132,6 +159,11 @@ void QskSkinHintTableEditor::setGradient( QskAspect aspect, const QskGradient& g
|
|||
setColorHint( aspect, gradient );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setGradient( QskAspect aspect, const QskGradient& gradient, QskAspect::State state )
|
||||
{
|
||||
setColorHint( aspect, QVariant::fromValue( gradient ), state );
|
||||
}
|
||||
|
||||
QskGradient QskSkinHintTableEditor::gradient( QskAspect aspect ) const
|
||||
{
|
||||
return colorHint< QskGradient >( aspect );
|
||||
|
@ -279,6 +311,12 @@ void QskSkinHintTableEditor::setBoxShape(
|
|||
setMetricHint( aspectShape( aspect ), shape );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setBoxShape(
|
||||
QskAspect aspect, const QskBoxShapeMetrics& shape, QskAspect::State state )
|
||||
{
|
||||
setMetricHint( aspectShape( aspect ), QVariant::fromValue( shape ), state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::removeBoxShape( QskAspect aspect )
|
||||
{
|
||||
return removeMetricHint( aspectShape( aspect ) );
|
||||
|
@ -309,6 +347,12 @@ void QskSkinHintTableEditor::setBoxBorderMetrics(
|
|||
setMetricHint( aspectBorder( aspect ), borderMetrics );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setBoxBorderMetrics(
|
||||
QskAspect aspect, const QskBoxBorderMetrics& borderMetrics, QskAspect::State state )
|
||||
{
|
||||
setMetricHint( aspectBorder( aspect ), QVariant::fromValue( borderMetrics ), state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::removeBoxBorderMetric( QskAspect aspect )
|
||||
{
|
||||
return removeMetricHint( aspectBorder( aspect ) );
|
||||
|
@ -325,6 +369,12 @@ void QskSkinHintTableEditor::setBoxBorderColors(
|
|||
setColorHint( aspectBorder( aspect ), borderColors );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setBoxBorderColors(
|
||||
QskAspect aspect, const QskBoxBorderColors& borderColors, QskAspect::State state )
|
||||
{
|
||||
setColorHint( aspectBorder( aspect ), QVariant::fromValue( borderColors ), state );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setBoxBorderColors( QskAspect aspect,
|
||||
const QColor& left, const QColor& top, const QColor& right, const QColor& bottom )
|
||||
{
|
||||
|
@ -341,3 +391,104 @@ QskBoxBorderColors QskSkinHintTableEditor::boxBorderColors( QskAspect aspect ) c
|
|||
{
|
||||
return colorHint< QskBoxBorderColors >( aspectBorder( aspect ) );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::forAllCombinationsSetHint( QskAspect::State state,
|
||||
QskAspect aspect, const QVariant& hint )
|
||||
{
|
||||
uint population = qPopulationCount( quint16( state ) );
|
||||
|
||||
// first find out which bits are set:
|
||||
quint16 s = state;
|
||||
uint i;
|
||||
std::vector< quint16 > positions;
|
||||
positions.reserve( population );
|
||||
|
||||
// use this instead of calling reserve(), trading execution time against space:
|
||||
// ### even better: don't store positions, but calculate pairs of indices
|
||||
// quint16 bla[16];
|
||||
|
||||
while( s != 0 ) // O(population)
|
||||
{
|
||||
i = 15 - qCountLeadingZeroBits( s );
|
||||
quint16 testBit = ( 1 << i );
|
||||
positions.push_back( i );
|
||||
s = s ^ testBit;
|
||||
}
|
||||
|
||||
for( uint i = 1; i <= population; ++i ) // O(population)
|
||||
{
|
||||
calculateCombinationsSetHint( positions, 0, positions.size() - 1, 0, i, QskAspect::NoState, aspect, hint );
|
||||
}
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::calculateCombinationsSetHint( const std::vector< quint16 >& arr,
|
||||
int start, int end, int index, int r,
|
||||
QskAspect::State state, QskAspect aspect,
|
||||
const QVariant& hint )
|
||||
{
|
||||
if( index == r )
|
||||
{
|
||||
setHint( aspect | state, hint );
|
||||
}
|
||||
|
||||
for( int i = start; i <= end && end - i + 1 >= r - index; i++ )
|
||||
{
|
||||
auto currentState = state | static_cast< QskAspect::State >( 1 << arr[i] );
|
||||
calculateCombinationsSetHint( arr, i + 1, end, index + 1, r, currentState, aspect, hint );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskSkinHintTableEditor::forAllCombinationsRemoveHint( QskAspect::State state,
|
||||
QskAspect aspect )
|
||||
{
|
||||
uint population = qPopulationCount( quint16( state ) );
|
||||
|
||||
// first find out which bits are set:
|
||||
quint16 s = state;
|
||||
uint i;
|
||||
std::vector< quint16 > positions;
|
||||
positions.reserve( population );
|
||||
|
||||
// use this instead of calling reserve(), trading execution time against space:
|
||||
// ### even better: don't store positions, but calculate pairs of indices
|
||||
// quint16 bla[16];
|
||||
|
||||
while( s != 0 ) // O(population)
|
||||
{
|
||||
i = 15 - qCountLeadingZeroBits( s );
|
||||
quint16 testBit = ( 1 << i );
|
||||
positions.push_back( i );
|
||||
s = s ^ testBit;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
for( uint i = 1; i <= population; ++i ) // O(population)
|
||||
{
|
||||
bool result = calculateCombinationsRemoveHint( positions, 0, positions.size() - 1, 0, i, QskAspect::NoState, aspect );
|
||||
ret = ret || result;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QskSkinHintTableEditor::calculateCombinationsRemoveHint( const std::vector< quint16 >& arr,
|
||||
int start, int end, int index, int r,
|
||||
QskAspect::State state, QskAspect aspect )
|
||||
{
|
||||
if( index == r )
|
||||
{
|
||||
return removeHint( aspect | state );
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
for( int i = start; i <= end && end - i + 1 >= r - index; i++ )
|
||||
{
|
||||
auto currentState = state | static_cast< QskAspect::State >( 1 << arr[i] );
|
||||
bool result = calculateCombinationsRemoveHint( arr, i + 1, end, index + 1, r, currentState, aspect );
|
||||
ret = ret || result;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -30,9 +30,11 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
// generic access
|
||||
|
||||
void setHint( QskAspect, const QVariant& );
|
||||
void setHint( QskAspect, const QVariant&, QskAspect::State );
|
||||
const QVariant& hint( QskAspect ) const;
|
||||
|
||||
bool removeHint( QskAspect );
|
||||
bool removeHint( QskAspect, QskAspect::State );
|
||||
QVariant takeHint( QskAspect );
|
||||
|
||||
bool hasHint( QskAspect ) const;
|
||||
|
@ -48,6 +50,7 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
// flag/metric/color
|
||||
|
||||
void setFlagHint( QskAspect, const QVariant& );
|
||||
void setFlagHint( QskAspect, const QVariant&, QskAspect::State );
|
||||
void removeFlagHint( QskAspect );
|
||||
QVariant flagHint( QskAspect ) const;
|
||||
|
||||
|
@ -55,6 +58,7 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
template< typename T > T flagHint( QskAspect ) const;
|
||||
|
||||
void setMetricHint( QskAspect, const QVariant& );
|
||||
void setMetricHint( QskAspect, const QVariant&, QskAspect::State );
|
||||
void removeMetricHint( QskAspect );
|
||||
QVariant metricHint( QskAspect ) const;
|
||||
|
||||
|
@ -62,6 +66,7 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
template< typename T > T metricHint( QskAspect ) const;
|
||||
|
||||
void setColorHint( QskAspect, const QVariant& );
|
||||
void setColorHint( QskAspect, const QVariant&, QskAspect::State );
|
||||
void removeColorHint( QskAspect );
|
||||
QVariant colorHint( QskAspect ) const;
|
||||
|
||||
|
@ -84,6 +89,7 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
void setHGradient( QskAspect, const QColor&, const QColor& );
|
||||
void setVGradient( QskAspect, const QColor&, const QColor& );
|
||||
void setGradient( QskAspect, const QskGradient& );
|
||||
void setGradient( QskAspect, const QskGradient&, QskAspect::State state );
|
||||
QskGradient gradient( QskAspect ) const;
|
||||
|
||||
void setStrutSize( QskAspect, const QSizeF& );
|
||||
|
@ -123,6 +129,7 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
void setBoxShape( QskAspect, qreal topLeft, qreal topRight,
|
||||
qreal bottomLeft, qreal bottomRight, Qt::SizeMode = Qt::AbsoluteSize );
|
||||
void setBoxShape( QskAspect, const QskBoxShapeMetrics& );
|
||||
void setBoxShape( QskAspect, const QskBoxShapeMetrics&, QskAspect::State );
|
||||
void removeBoxShape( QskAspect );
|
||||
QskBoxShapeMetrics boxShape( QskAspect ) const;
|
||||
|
||||
|
@ -131,16 +138,29 @@ class QSK_EXPORT QskSkinHintTableEditor
|
|||
void setBoxBorderMetrics( QskAspect, qreal left, qreal top,
|
||||
qreal right, qreal bottom, Qt::SizeMode = Qt::AbsoluteSize );
|
||||
void setBoxBorderMetrics( QskAspect, const QskBoxBorderMetrics& );
|
||||
void setBoxBorderMetrics( QskAspect, const QskBoxBorderMetrics&, QskAspect::State );
|
||||
void removeBoxBorderMetric( QskAspect );
|
||||
QskBoxBorderMetrics boxBorderMetrics( QskAspect ) const;
|
||||
|
||||
void setBoxBorderColors( QskAspect, const QskBoxBorderColors& );
|
||||
void setBoxBorderColors( QskAspect, const QskBoxBorderColors&, QskAspect::State );
|
||||
void setBoxBorderColors( QskAspect, const QColor& left, const QColor& top,
|
||||
const QColor& right, const QColor& bottom );
|
||||
void removeBoxBorderColors( QskAspect );
|
||||
QskBoxBorderColors boxBorderColors( QskAspect ) const;
|
||||
|
||||
private:
|
||||
void forAllCombinationsSetHint( QskAspect::State, QskAspect,
|
||||
const QVariant& hint );
|
||||
void calculateCombinationsSetHint( const std::vector< quint16 >& arr,
|
||||
int start, int end, int index, int r,
|
||||
QskAspect::State state, QskAspect aspect,
|
||||
const QVariant& hint );
|
||||
bool forAllCombinationsRemoveHint( QskAspect::State, QskAspect );
|
||||
bool calculateCombinationsRemoveHint( const std::vector< quint16 >& arr,
|
||||
int start, int end, int index, int r,
|
||||
QskAspect::State state, QskAspect aspect );
|
||||
|
||||
QskSkinHintTable* m_table = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2021 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include <QskBox.h>
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskSkin.h>
|
||||
#include <QskSkinHintTableEditor.h>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QtTest>
|
||||
|
||||
class TestSkinHints : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void setHints();
|
||||
void removeHints();
|
||||
|
||||
private:
|
||||
QskSkin m_skin;
|
||||
QskSkinHintTableEditor ed = QskSkinHintTableEditor( &m_skin.hintTable() );
|
||||
};
|
||||
|
||||
void TestSkinHints::setHints()
|
||||
{
|
||||
QskBoxBorderColors colors;
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == QColor() );
|
||||
|
||||
ed.setBoxBorderColors( QskBox::Panel, { Qt::red },
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Disabled );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Hovered );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Focused );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Disabled | QskControl::Hovered );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Disabled | QskControl::Focused );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Hovered | QskControl::Focused );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
|
||||
colors = ed.boxBorderColors( QskBox::Panel | QskControl::Disabled | QskControl::Hovered | QskControl::Focused );
|
||||
QVERIFY( colors.colorAt( Qt::TopEdge ) == Qt::red );
|
||||
}
|
||||
|
||||
void TestSkinHints::removeHints()
|
||||
{
|
||||
bool removed = ed.removeHint( QskBox::Panel | QskAspect::Color,
|
||||
QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
QVERIFY( removed == false );
|
||||
|
||||
ed.setColorHint( QskBox::Panel, QColor( Qt::green ),
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
|
||||
removed = ed.removeHint( QskBox::Panel | QskAspect::Color,
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
QVERIFY( removed == true );
|
||||
|
||||
removed = ed.removeHint( QskBox::Panel | QskAspect::Color,
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
QVERIFY( removed == false );
|
||||
|
||||
ed.setColorHint( QskBox::Panel, QColor( Qt::green ),
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
| QskControl::Focused
|
||||
);
|
||||
|
||||
removed = ed.removeHint( QskBox::Panel | QskAspect::Color,
|
||||
QskControl::Disabled
|
||||
| QskControl::Hovered
|
||||
);
|
||||
QVERIFY( removed == true );
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestSkinHints)
|
||||
#include "SkinHints.moc"
|
|
@ -0,0 +1,6 @@
|
|||
CONFIG += testcase qskinny
|
||||
TARGET = tst_skinhints
|
||||
SOURCES += SkinHints.cpp
|
||||
QT += testlib
|
||||
|
||||
INCLUDEPATH *= $${QSK_DIRS}
|
|
@ -0,0 +1,4 @@
|
|||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
skinhints
|
Loading…
Reference in New Issue