code cleanup

This commit is contained in:
Uwe Rathmann 2020-12-18 16:32:54 +01:00
parent 23bbab7820
commit ef755011df
7 changed files with 150 additions and 165 deletions

View File

@ -64,23 +64,25 @@ namespace
using Q = Speedometer; using Q = Speedometer;
setBoxBorderMetrics( Q::Panel, 5 ); setBoxBorderMetrics( Q::Panel, 5 );
setBoxShape( Q::Panel, 30, Qt::RelativeSize );
setGradient( Q::Panel, setGradient( Q::Panel,
QskGradient( QskGradient::Vertical, color2, color4 ) ); QskGradient( QskGradient::Vertical, color2, color4 ) );
setBoxBorderColors( Q::Panel, color3 ); setBoxBorderColors( Q::Panel, color3 );
setBoxBorderMetrics( Q::NeedleHead, 5 ); setBoxBorderMetrics( Q::Knob, 5 );
setMetric( Q::NeedleHead | Size, 10 ); setStrutSize( Q::Knob, 20, 20 );
setGradient( Q::NeedleHead, color2 ); setBoxShape( Q::Knob, 100, Qt::RelativeSize );
setBoxBorderColors( Q::NeedleHead, color4 ); setGradient( Q::Knob, color2 );
setBoxBorderColors( Q::Knob, color4 );
setMetric( Q::Needle | Size, 4 ); setMetric( Q::Needle | Size, 4 );
setMetric( Q::Needle | Margin, 15 ); setMetric( Q::Needle | Margin, 15 );
setColor( Q::Needle, color4 ); setColor( Q::Needle, color4 );
setSpacing( Q::Labels, 3 ); setSpacing( Q::TickLabels, 3 );
setStrutSize( Q::Labels, 3, 25 ); setStrutSize( Q::TickLabels, 3, 25 );
setColor( Q::Labels, color4 ); setColor( Q::TickLabels, color4 );
setFontRole( Q::Labels, QskSkin::SmallFont ); setFontRole( Q::TickLabels, QskSkin::SmallFont );
} }
{ {
@ -113,23 +115,24 @@ namespace
using Q = Speedometer; using Q = Speedometer;
setBoxBorderMetrics( Q::Panel, 2 ); setBoxBorderMetrics( Q::Panel, 2 );
setBoxShape( Q::Panel, 100, Qt::RelativeSize );
setGradient( Q::Panel, color1 ); setGradient( Q::Panel, color1 );
setBoxBorderColors( Q::Panel, color3 ); setBoxBorderColors( Q::Panel, color3 );
setBoxBorderMetrics( Q::NeedleHead, 2 ); setBoxBorderMetrics( Q::Knob, 2 );
setMetric( Q::NeedleHead | Size, 15 ); setStrutSize( Q::Knob, 30, 30 );
setGradient( Q::NeedleHead, setBoxShape( Q::Knob, 100, Qt::RelativeSize );
setGradient( Q::Knob,
QskGradient( QskGradient::Diagonal, color2, color1 ) ); QskGradient( QskGradient::Diagonal, color2, color1 ) );
// setBoxBorderColors( Q::NeedleHead, color4 );
setMetric( Q::Needle | Size, 2 ); setMetric( Q::Needle | Size, 2 );
setMetric( Q::Needle | Margin, 10 ); setMetric( Q::Needle | Margin, 10 );
setColor( Q::Needle, color2 ); setColor( Q::Needle, color2 );
setSpacing( Q::Labels, 4 ); setSpacing( Q::TickLabels, 4 );
setStrutSize( Q::Labels, 2, 15 ); setStrutSize( Q::TickLabels, 2, 15 );
setColor( Q::Labels, color4 ); setColor( Q::TickLabels, color4 );
setFontRole( Q::Labels, QskSkin::SmallFont ); setFontRole( Q::TickLabels, QskSkin::SmallFont );
} }
} }
}; };

View File

@ -9,8 +9,8 @@
#include <QskSkinnable.h> #include <QskSkinnable.h>
QSK_SUBCONTROL( Speedometer, Panel ) QSK_SUBCONTROL( Speedometer, Panel )
QSK_SUBCONTROL( Speedometer, Labels ) QSK_SUBCONTROL( Speedometer, TickLabels )
QSK_SUBCONTROL( Speedometer, NeedleHead ) QSK_SUBCONTROL( Speedometer, Knob )
QSK_SUBCONTROL( Speedometer, Needle ) QSK_SUBCONTROL( Speedometer, Needle )
Speedometer::Speedometer( QQuickItem* parent ) Speedometer::Speedometer( QQuickItem* parent )
@ -18,14 +18,14 @@ Speedometer::Speedometer( QQuickItem* parent )
{ {
} }
QVector< QString > Speedometer::labels() const QVector< QString > Speedometer::tickLabels() const
{ {
return m_labels; return m_tickLabels;
} }
void Speedometer::setLabels( const QVector< QString >& labels ) void Speedometer::setTickLabels( const QVector< QString >& labels )
{ {
m_labels = labels; m_tickLabels = labels;
} }
#include "moc_Speedometer.cpp" #include "moc_Speedometer.cpp"

View File

@ -13,15 +13,15 @@ class Speedometer : public QskBoundedValueInput
Q_OBJECT Q_OBJECT
public: public:
QSK_SUBCONTROLS( Panel, Labels, NeedleHead, Needle ) QSK_SUBCONTROLS( Panel, TickLabels, Knob, Needle )
Speedometer( QQuickItem* parent = nullptr ); Speedometer( QQuickItem* parent = nullptr );
QVector< QString > labels() const; QVector< QString > tickLabels() const;
void setLabels( const QVector< QString >& ); void setTickLabels( const QVector< QString >& );
private: private:
QVector< QString > m_labels; QVector< QString > m_tickLabels;
}; };
#endif #endif

View File

@ -60,7 +60,7 @@ namespace
for ( int i = 0; i < labelsCount; i++ ) for ( int i = 0; i < labelsCount; i++ )
labels += QString::number( i ); labels += QString::number( i );
setLabels( labels ); setTickLabels( labels );
} }
}; };
@ -74,7 +74,7 @@ namespace
setMaximum( 35 ); setMaximum( 35 );
setValue( -90 ); setValue( -90 );
constexpr int labelsCount = 23; constexpr int labelsCount = 17;
QVector< QString > labels; QVector< QString > labels;
labels.reserve( labelsCount ); labels.reserve( labelsCount );
@ -82,7 +82,7 @@ namespace
for ( int i = 0; i < labelsCount; i++ ) for ( int i = 0; i < labelsCount; i++ )
labels.append( QString::number( i * 10 ) ); labels.append( QString::number( i * 10 ) );
setLabels( labels ); setTickLabels( labels );
} }
void updateValue() void updateValue()
@ -101,7 +101,7 @@ namespace
setMaximum( 345 ); setMaximum( 345 );
setValue( 330 ); setValue( 330 );
setLabels( { "0", "", "1/2", "", "1/1" } ); setTickLabels( { "0", "", "1/2", "", "1/1" } );
} }
void updateValue() void updateValue()

View File

@ -16,16 +16,17 @@
#include <QskFunctions.h> #include <QskFunctions.h>
#include <QFontMetrics> #include <QFontMetrics>
#include <QLineF>
#include <QSGFlatColorMaterial> #include <QSGFlatColorMaterial>
#include <QtMath> #include <QtMath>
namespace namespace
{ {
class TicksNode : public QSGGeometryNode class LinesNode : public QSGGeometryNode
{ {
public: public:
TicksNode() LinesNode( int lineCount = 0 )
: m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 ) : m_geometry( QSGGeometry::defaultAttributes_Point2D(), 2 * lineCount )
{ {
#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 )
m_geometry.setDrawingMode( QSGGeometry::DrawLines ); m_geometry.setDrawingMode( QSGGeometry::DrawLines );
@ -40,29 +41,70 @@ namespace
void setColor( const QColor& color ) void setColor( const QColor& color )
{ {
m_material.setColor( color ); if ( color != m_material.color() )
{
m_material.setColor( color );
markDirty( QSGNode::DirtyMaterial );
}
} }
private: private:
QSGFlatColorMaterial m_material; QSGFlatColorMaterial m_material;
QSGGeometry m_geometry; QSGGeometry m_geometry;
}; };
} // namespace
class TicksNode : public LinesNode
{
public:
TicksNode()
{
}
};
class NeedleNode : public LinesNode
{
public:
NeedleNode()
: LinesNode( 1 )
{
}
void setData( const QLineF& line, qreal width )
{
auto vertexData = geometry()->vertexDataAsPoint2D();
vertexData[ 0 ].set( line.x1(), line.y1() );
vertexData[ 1 ].set( line.x2(), line.y2() );
geometry()->setLineWidth( width );
geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry );
}
};
}
SpeedometerSkinlet::SpeedometerSkinlet( QskSkin* skin ) SpeedometerSkinlet::SpeedometerSkinlet( QskSkin* skin )
: QskSkinlet( skin ) : QskSkinlet( skin )
{ {
setNodeRoles( { PanelRole, LabelsRole, NeedleRole } ); setNodeRoles( { PanelRole, NeedleRole, KnobRole, LabelsRole } );
} }
SpeedometerSkinlet::~SpeedometerSkinlet() = default; QRectF SpeedometerSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subcontrol ) const
QRectF SpeedometerSkinlet::subControlRect( const QskSkinnable*,
const QRectF& contentsRect, QskAspect::Subcontrol ) const
{ {
const auto extent = qMin( contentsRect.width(), contentsRect.height() ); QRectF r;
QRectF r( 0.0, 0.0, extent, extent ); if ( subcontrol == Speedometer::Knob )
{
const auto size = skinnable->strutSizeHint( Speedometer::Knob );
r.setSize( size );
}
else
{
const auto extent = qMin( contentsRect.width(), contentsRect.height() );
r.setSize( QSizeF( extent, extent ) );
}
r.moveCenter( contentsRect.center() ); r.moveCenter( contentsRect.center() );
return r; return r;
@ -76,98 +118,65 @@ QSGNode* SpeedometerSkinlet::updateSubNode(
switch ( nodeRole ) switch ( nodeRole )
{ {
case PanelRole: case PanelRole:
return updatePanelNode( speedometer, node ); return updateBoxNode( speedometer, node, Speedometer::Panel );
case LabelsRole: case KnobRole:
return updateLabelsNode( speedometer, node ); return updateBoxNode( speedometer, node, Speedometer::Knob );
case NeedleRole: case NeedleRole:
return updateNeedleNode( speedometer, node ); return updateNeedleNode( speedometer, node );
case LabelsRole:
return updateLabelsNode( speedometer, node );
default: default:
return nullptr; return nullptr;
} }
} }
QSGNode* SpeedometerSkinlet::updatePanelNode(
const Speedometer* speedometer, QSGNode* node ) const
{
auto boxNode = static_cast< QskBoxNode* >( node );
if ( boxNode == nullptr )
{
boxNode = new QskBoxNode;
}
const auto panelRect = subControlRect(
speedometer, speedometer->contentsRect(), Speedometer::Panel );
const qreal radius = panelRect.width() / 2;
QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius );
QskBoxBorderMetrics borderMetrics = speedometer->boxBorderMetricsHint( Speedometer::Panel );
QskBoxBorderColors borderColors = speedometer->boxBorderColorsHint( Speedometer::Panel );
QskGradient gradient = speedometer->gradientHint( Speedometer::Panel );
boxNode->setBoxData( panelRect, shapeMetrics, borderMetrics, borderColors, gradient );
return boxNode;
}
QSGNode* SpeedometerSkinlet::updateLabelsNode( QSGNode* SpeedometerSkinlet::updateLabelsNode(
const Speedometer* speedometer, QSGNode* node ) const const Speedometer* speedometer, QSGNode* node ) const
{ {
using Q = Speedometer; using Q = Speedometer;
const int labelsCount = speedometer->labels().count(); const auto labels = speedometer->tickLabels();
// ### actually, we could draw labels with only one entry // ### actually, we could draw labels with only one entry
if ( labelsCount <= 1 ) if ( labels.count() <= 1 )
{
return nullptr; return nullptr;
}
auto ticksNode = static_cast< TicksNode* >( node ); auto ticksNode = static_cast< TicksNode* >( node );
if ( ticksNode == nullptr ) if ( ticksNode == nullptr )
{
ticksNode = new TicksNode(); ticksNode = new TicksNode();
}
const auto color = speedometer->color( Q::Labels ); const auto color = speedometer->color( Q::TickLabels );
ticksNode->setColor( color ); ticksNode->setColor( color );
const auto startAngle = speedometer->minimum(); const auto startAngle = speedometer->minimum();
const auto endAngle = speedometer->maximum(); const auto endAngle = speedometer->maximum();
const auto step = ( endAngle - startAngle ) / ( labelsCount - 1 ); const auto step = ( endAngle - startAngle ) / ( labels.count() - 1 );
auto geometry = ticksNode->geometry(); auto geometry = ticksNode->geometry();
geometry->allocate( labelsCount * 2 ); geometry->allocate( labels.count() * 2 );
auto vertexData = geometry->vertexDataAsPoint2D(); auto vertexData = geometry->vertexDataAsPoint2D();
memset( vertexData, 0, static_cast< size_t >( geometry->vertexCount() ) );
const auto panelMargins = speedometer->marginHint( Q::Panel ); auto scaleRect = this->scaleRect( speedometer );
auto panelRect = subControlRect( const auto center = scaleRect.center();
speedometer, speedometer->contentsRect(), Q::Panel ); const auto radius = 0.5 * scaleRect.width();
panelRect = panelRect.marginsRemoved( panelMargins );
QPointF center = QPointF( panelRect.x() + panelRect.width() / 2, const auto spacing = speedometer->spacingHint( Q::TickLabels );
panelRect.y() + panelRect.height() / 2 ); QFontMetricsF fontMetrics( speedometer->effectiveFont( Q::TickLabels ) );
const auto radius = static_cast< float >( panelRect.width() / 2 );
const auto spacing = speedometer->spacingHint( Q::Labels );
QFontMetricsF fontMetrics( speedometer->effectiveFont( Q::Labels ) );
auto angle = startAngle; auto angle = startAngle;
const auto labels = speedometer->labels();
const auto tickSize = speedometer->strutSizeHint( Q::Labels ); const auto tickSize = speedometer->strutSizeHint( Q::TickLabels );
const auto needleRadius = radius - tickSize.height(); const auto needleRadius = radius - tickSize.height();
// Create a series of tickmarks from minimum to maximum // Create a series of tickmarks from minimum to maximum
for ( int i = 0; i < labelsCount; ++i, angle += step ) for ( int i = 0; i < labels.count(); ++i, angle += step )
{ {
const qreal cos = qFastCos( qDegreesToRadians( angle ) ); const qreal cos = qFastCos( qDegreesToRadians( angle ) );
const qreal sin = qFastSin( qDegreesToRadians( angle ) ); const qreal sin = qFastSin( qDegreesToRadians( angle ) );
@ -196,7 +205,7 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode(
const auto numbersX = xEnd - ( spacing * cos ) + adjustX; const auto numbersX = xEnd - ( spacing * cos ) + adjustX;
const auto numbersY = yEnd - ( spacing * sin ) + adjustY; const auto numbersY = yEnd - ( spacing * sin ) + adjustY;
QRectF numbersRect( numbersX, numbersY, w, h ); const QRectF numbersRect( numbersX, numbersY, w, h );
QskTextNode* numbersNode; QskTextNode* numbersNode;
@ -209,15 +218,12 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode(
numbersNode = new QskTextNode(); numbersNode = new QskTextNode();
} }
const auto font = speedometer->effectiveFont( Q::Labels ); const auto font = speedometer->effectiveFont( Q::TickLabels );
numbersNode->setTextData( speedometer, text, numbersRect, font, QskTextOptions(), numbersNode->setTextData( speedometer, text, numbersRect, font, QskTextOptions(),
QskTextColors( color ), Qt::AlignCenter | Qt::AlignHCenter, Qsk::Normal ); QskTextColors( color ), Qt::AlignCenter | Qt::AlignHCenter, Qsk::Normal );
if ( ticksNode->childCount() <= i ) if ( ticksNode->childCount() <= i )
{
ticksNode->appendChildNode( numbersNode ); ticksNode->appendChildNode( numbersNode );
}
// ### remove nodes in case they are superfluous
} }
} }
@ -232,76 +238,45 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode(
QSGNode* SpeedometerSkinlet::updateNeedleNode( QSGNode* SpeedometerSkinlet::updateNeedleNode(
const Speedometer* speedometer, QSGNode* node ) const const Speedometer* speedometer, QSGNode* node ) const
{ {
using namespace QskAspect;
using Q = Speedometer; using Q = Speedometer;
auto needleNode = static_cast< TicksNode* >( node ); auto needleNode = static_cast< NeedleNode* >( node );
if ( needleNode == nullptr ) if ( needleNode == nullptr )
needleNode = new TicksNode(); needleNode = new NeedleNode();
QskBoxNode* boxNode; const auto line = needlePoints( speedometer );
const auto width = speedometer->metric( Q::Needle | QskAspect::Size );
if ( needleNode->childCount() == 0 ) needleNode->setData( line, width * 2 );
{ needleNode->setColor( speedometer->color( Q::Needle ) );
boxNode = new QskBoxNode();
needleNode->appendChildNode( boxNode );
}
else
{
boxNode = static_cast< QskBoxNode* >( needleNode->childAtIndex( 0 ) );
}
const auto margins = speedometer->marginHint( Q::Panel );
auto panelRect = subControlRect(
speedometer, speedometer->contentsRect(), Q::Panel );
panelRect = panelRect.marginsRemoved( margins );
const auto radius = speedometer->metric( Q::NeedleHead | Size );
const QPointF center = panelRect.center();
const auto borderMetrics = speedometer->boxBorderMetricsHint( Q::NeedleHead );
const auto borderColors = speedometer->boxBorderColorsHint( Q::NeedleHead );
const auto gradient = speedometer->gradientHint( Q::NeedleHead );
QRectF centerNodeRect( center.x() - radius, center.y() - radius, 2 * radius, 2 * radius );
boxNode->setBoxData( centerNodeRect, radius, borderMetrics, borderColors, gradient );
QColor color = speedometer->color( Q::Needle );
needleNode->setColor( color );
auto panelRadius = static_cast< float >( panelRect.width() / 2 );
const auto needleWidth = speedometer->metric( Q::Needle | Size );
const auto needleMargin = speedometer->metric( Q::Needle | Margin );
const float xStart = center.x();
const float yStart = center.y();
const float angle = speedometer->value();
const qreal cosine = qCos( qDegreesToRadians( angle ) );
const qreal sine = qSin( qDegreesToRadians( angle ) );
const float needleRadius = panelRadius - needleMargin;
const float xEnd = center.x() + needleRadius * cosine;
const float yEnd = center.y() + needleRadius * sine;
auto geometry = needleNode->geometry();
geometry->allocate( 2 );
auto vertexData = geometry->vertexDataAsPoint2D();
memset( vertexData, 0, static_cast< size_t >( geometry->vertexCount() ) );
vertexData[ 0 ].set( xStart, yStart );
vertexData[ 1 ].set( xEnd, yEnd );
geometry->setLineWidth( 2 * needleWidth );
geometry->markVertexDataDirty();
needleNode->markDirty( QSGNode::DirtyGeometry );
return needleNode; return needleNode;
} }
QRectF SpeedometerSkinlet::scaleRect( const Speedometer* speedometer ) const
{
using Q = Speedometer;
const auto margins = speedometer->marginHint( Q::Panel );
auto r = speedometer->subControlRect( Q::Panel );
r = r.marginsRemoved( margins );
return r;
}
QLineF SpeedometerSkinlet::needlePoints( const Speedometer* speedometer ) const
{
const auto r = scaleRect( speedometer );
const auto margin = speedometer->metric(
Speedometer::Needle | QskAspect::Margin );
QLineF line;
line.setP1( r.center() );
line.setLength( 0.5 * r.width() - margin );
line.setAngle( -speedometer->value() );
return line;
}
#include "moc_SpeedometerSkinlet.cpp" #include "moc_SpeedometerSkinlet.cpp"

View File

@ -19,11 +19,11 @@ class SpeedometerSkinlet : public QskSkinlet
{ {
PanelRole, PanelRole,
LabelsRole, LabelsRole,
KnobRole,
NeedleRole NeedleRole
}; };
Q_INVOKABLE SpeedometerSkinlet( QskSkin* skin = nullptr ); Q_INVOKABLE SpeedometerSkinlet( QskSkin* skin = nullptr );
~SpeedometerSkinlet() override;
QRectF subControlRect( const QskSkinnable*, QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override; const QRectF&, QskAspect::Subcontrol ) const override;
@ -33,7 +33,9 @@ class SpeedometerSkinlet : public QskSkinlet
quint8 nodeRole, QSGNode* node ) const override; quint8 nodeRole, QSGNode* node ) const override;
private: private:
QSGNode* updatePanelNode( const Speedometer*, QSGNode* ) const; QRectF scaleRect( const Speedometer* ) const;
QLineF needlePoints( const Speedometer* ) const;
QSGNode* updateLabelsNode( const Speedometer*, QSGNode* ) const; QSGNode* updateLabelsNode( const Speedometer*, QSGNode* ) const;
QSGNode* updateNeedleNode( const Speedometer*, QSGNode* ) const; QSGNode* updateNeedleNode( const Speedometer*, QSGNode* ) const;
}; };

View File

@ -11,12 +11,17 @@
#include <QskSetup.h> #include <QskSetup.h>
#include <QskSkinManager.h> #include <QskSkinManager.h>
#include <SkinnyShortcut.h> #include <QskObjectCounter.h>
#include <SkinnyShortcut.h>
#include <QGuiApplication> #include <QGuiApplication>
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
#ifdef ITEM_STATISTICS
QskObjectCounter counter( true );
#endif
qskSkinManager->setPluginPaths( QStringList() ); // no skin plugins qskSkinManager->setPluginPaths( QStringList() ); // no skin plugins
qskSkinManager->registerFactory( QStringLiteral( "sample" ), new SkinFactory() ); qskSkinManager->registerFactory( QStringLiteral( "sample" ), new SkinFactory() );